• 走进C的世界-那些年我们常犯的错---keyword相关


         近期一段时间參加一些面试,发现非常多细节的问题自己已经变得非常模糊了。对一些曾经常常遇到的错误。如今也说不出原因了。

    而且在编码过程中也相同犯这些错误。

    特别写一个博客来记录这些我们常常遇到的错误。自己也在gitHUb上创建了一个库。来总结这些错误。

    地址:https://github.com/jinshaohui/C_Error_problem。希望大家有遇到相同问题的都提交到这里。

          废话少说。来正题吧,先来说说数据类型使用过程中遇到的问题吧!

         看以下的代码会输入什么?为什么 ?

    /*File : type_conversion.c
     *Auth : sjin
     *Date : 20141018
     *Mail : 413977243@qq.com
     */
    
    #include <stdio.h>
    
    int array[] = {10,20,30,40};
    #define TOTAL_EMEMENTS (sizeof(array)/sizeof(array[0]))
    
    /*另外一个样例
     *代码输出什么?为什么?
     * */
    int fun()
    {
        unsigned int a = 6;
        int b = -20;
    
        (a + b > 6)? puts("a + b > 6"):puts("a + b < 6");
    }
    
    int main()
    {
        int d = -1;
    
        if (d <= TOTAL_EMEMENTS){
            printf("##[sjin] : the array total emements is %d
    ",TOTAL_EMEMENTS);
        }else {
            printf("##[sjin] : the array is empty!
    ");
        }
    
        fun();
    
        return 0;
    }
    
     

    输入例如以下:

    ##[sjin] : the array is empty!
    a + b > 6
    
       TOTAL_EMEMENTS  所定义的值是unsigned int类型(由于sizeif返回值是无符号的),if语句在unsigned int 和int之间測试相等性 。所以d被升级为unsigend int类型。-1转换为unsigned int类型是一个巨大的整数。致使表达式的值为假。所以在比較前,须要对宏定义前加int类型的强制转换。

    这个问题就是潜在类型转换导致的。

    函数fun()中的错误也相同是这个问题。

        在对宏定义中。使用以下语句:

    #define TOTAL_EMEMENTS (sizeof(array)/sizeof(array[0]))

       而不是:

    #define TOTAL_EMEMENTS (sizeof(array)/sizeof(int))

       非常明显。在代码可扩展性方面。我们在不改变#define语句的情况下能够任意改变数据的基本类型(int变成char).

      

      sizeof  是keyword而不是函数,看以下的代码:

    /*File : sizeof.c
     *Auth : sjin
     *Date : 20141018
     *Mail : 413977243@qq.com
     */
    #include <stdio.h>
    /*sizeof 是keyword,不是函数
     *计算数据空间的字节数
     * */
    
    void fun(char b[100])
    {
        printf("##[sjin] in fun sizeof(b):	%d 
    ",sizeof(b));
    
    }
    
    int main()
    {
        double *p = NULL;
        char a[100] = {''};
        double *(*b)[3][6];
        int d = 0;
    
        printf("##[sjin] sizeof(int):	%d 
    ",sizeof(int));
        printf("##[sjin] sizeof(d):	%d 
    ",sizeof(d));
        printf("##[sjin] sizeof d:	%d 
    
    ",sizeof d );
    
        //以下编译错误
        //printf("##[sjin] sizeof int:	%d 
    
    ",sizeof int );
    
        printf("##[sjin] sizeof(p):	%d 
    ",sizeof(p)); //p是一个指针
        printf("##[sjin] sizeof(*p):	%d 
    ",sizeof(*p));//*p 为一个double的变量
        printf("##[sjin] sizeof(a):	%d 
    ",sizeof(a));//a是一个数组
        printf("##[sjin] sizeof(a[0]):	%d 
    ",sizeof(a[0]));//a[0] 是一个char型变量
        printf("##[sjin] sizeof(&a):	%d 
    ",sizeof(&a));//&a 是a的地址
        printf("##[sjin] sizeof(&a[0]):	%d 
    ",sizeof(&a[0]));//&a[0] 是a[0]的地址
        printf("##[sjin] sizeof(b):	%d 
    ",sizeof(b));
        printf("##[sjin] sizeof(*b):	%d 
    ",sizeof(*b));
        printf("##[sjin] sizeof(**b):	%d 
    ",sizeof(**b));
        printf("##[sjin] sizeof(***b):	%d 
    ",sizeof(***b));
        printf("##[sjin] sizeof(****b):	%d 
    ",sizeof(****b));
    
        fun(a);
    
    }
    
    输入例如以下:

     
    ##[sjin] sizeof(int):   4
    ##[sjin] sizeof(d):     4
    ##[sjin] sizeof d:      4
    
    ##[sjin] sizeof(p):     4
    ##[sjin] sizeof(*p):    8
    ##[sjin] sizeof(a):     100
    ##[sjin] sizeof(a[0]):  1
    ##[sjin] sizeof(&a):    4
    ##[sjin] sizeof(&a[0]): 4
    ##[sjin] sizeof(b):     4
    ##[sjin] sizeof(*b):    72
    ##[sjin] sizeof(**b):   24
    ##[sjin] sizeof(***b):  4
    ##[sjin] sizeof(****b): 8
    ##[sjin] in fun sizeof(b):      4
    
     
        sizeof int 表示什么啊?int 前面加一个keyword?类型扩展?明显不对。我们能够在 int 前加 unsigned,const 等keyword但不能加 sizeof。好,记住:sizeof 在计算 变量所占空间大小时, 括号能够省略.

       来说下函数传參,数组作为形參时,当作是一个指针, 所以是一个指针的大小。

    double *(*b)[3][6]; 这个比較难理解。
    b是一个指向double *[3][6] 类型的指针。所以大小也为4个字节。
    *b 是表示一个double*【3】【6】多维数组的类型。而数组元素都是double*类型的指针。所以
    sizeof(*b) = 3*6*sizeof(double*) = 72
    **b是表示一个 double*【6】的数组,所以sizeof(**b) = 6*sizeof(double*) = 24
    ***b是表示一个double*的元素指针,所以sizeof(***b) = sizeof(double*) = 4
    ****b是表示一个double类型的数值。所以sizeof(****b) = sizeof(double) = 8

    union 联合体

         考虑存储模式:大端模式和小端模式。
    大端模式(Big_endian) :字数据的 高字节存储在 低地址中,而字数据的 低字节则存放
    在 高地址中。
    小端模式(Little_endian) :字数据的 高字节存储在 高地址中,而字数据的 低字节则存放
    在 低地址中。
    union 型数据所占的空间等于其最大的成员所占的空间。对 union 型的成员的存取都是
    相对于该联合体基地址的偏移量为 0 处開始, 也就是联合体的訪问不论对哪个变量的存取都
    是从 union 的首地址位置開始。

       

    /*File : union.c
     *Auth : sjin
     *Date : 20141022
     *Mail : 413977243@qq.com
     */
    
    #include <stdio.h>
    /*这里来说明面试中常常问的一个问题
     *推断系统的大小端问题
     *存储模式:大端模式和小端模式。

    * 大端模式(Big_endian) :字数据的 高字节存储在 低地址中,而字数据的 低字节 则存放在高地址中。 * 小端模式(Little_endian) :字数据的 高字节存储在 高地址中,而字数据的 低字节则存放在低地址中。

    *union 型数据所占的空间等于其最大的成员所占的空间。对 union 型的成员的存取都是 *相对于该联合体基地址的偏移量为 0 处開始, 也就是联合体的訪问不论对哪个变量的存取都 *是从 union 的首地址位置開始. */ /* True: 小端模式 * False:大端模式 */ int checkSystem() { union check{ int i; char ch; }c; c.i = 1; return (c.ch == 1); } int main() { if(checkSystem()){ printf("当前系统为小端模式 "); }else{ printf("当前系统为大端模式 "); } return 0; }


    声明

      声明器是C语言声明的非常重要成份,他是全部声明的核心内容。简单的说:声明器就是标识符以及与它组合在一起的不论什么指针、函数括号、数组下表等
    /*File : union.c
     *Auth : sjin
     *Date : 20141022
     *Mail : 413977243@qq.com
     */
    
    /*介绍一些声明。及const、typedef的使用方法
     */
    #include <stdio.h>
    typedef void(*ptr_to_func)(int);
    /*它表示ptr_to_func是一个函数指针。该函数
     *接受一个int參数。返回值为void
     */
    ptr_to_func signal(int,ptr_to_func);
    /*它表示signal是一个函数,它接收两个參数
     * 当中一个是int型,还有一个是ptr_to_func,
     *返回值是ptr_to_func型
     */
    
    int main()
    {
        char (*j)[20];//j是一个指向数组的指针,数组内有20个char型的元素
        j = (char (*)[20])malloc(20*sizeof(char));//申请空间
    
        int const a;//a是一个常整型
        int const *a;//a是一个指向常整型的指针
        const int *a;//a是一个指向常整型的指针
        int *const a;//a是一个指向整型的常指针
        const int *const a;//a是一个指向常整型的常指针
    
        char *const *(*next)();
        /*next 是一个指针,它指向一个函数。该函数的返回值是还有一个指针
         * 该 指针指向一个类型为char的常指针
         */
    
        return 0;
    }

    详细声明的解析方法,可參见这个博文

  • 相关阅读:
    ES6-11学习笔记--正则表达式的扩展
    ES6-11学习笔记--字符串的扩展
    ES6-11学习笔记--Map
    ES6-11学习笔记--Set
    ES6-11学习笔记--Symbol
    final
    MySQL
    爬虫1
    laravel
    HTML学习
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5126409.html
Copyright © 2020-2023  润新知