zoukankan      html  css  js  c++  java
  • C语言事实上不简单:sizeof

    问:C语言中一共同拥有多少个keyword?

    答:32个。

    答不上来的没关系。非常正常。我们玩的是程序的艺术。而不是背数字。

    只是这个特殊的数字1<<5也是非常好记的-.-。


    问:sizeof是函数还是keyword?

    第一次看到这个问题,你可能会认为有点莫名其妙,sizeof当然是函数了,由于sizeof后面都跟了个括号,这显然是函数的象征。

    可是既然我这么问了。你可能也猜到了,sizeof不是个函数,它是个keyword!长期以来由于sizeof的"标准使用方法",导致sizeof极easy被理解为一个函数。

    尝试执行以下的代码:

    #include <stdio.h>
    
    int main()
    {
        int num = 5;
        printf("%d
    ", sizeof(num));
        printf("%d
    ", sizeof(int));
        printf("%d
    ", sizeof num);
        getchar();
        return 0;
    }
    
    
    sizeof num竟然也能正确输出4,可见它真的不是函数。

    只是sizeof int就是错误的了。它会产生例如以下错误:

    error: expected primary-expression before "int"
    由于int前面仅仅能跟auto、unsigned等,况且sizeof int要怎么来理解?是想计算大小呢?还是想表示"sizeof"类型的int变量呢。

    查阅相关文档后总结例如以下:

    当要计算变量的大小,比如基本类型(int、double)的变量,结构体变量(实例)时。能够不用括号。

    当要计算一个类型时,不能省略括号。

    无论什么场合都加上个括号,一是统一,而是能使程序可读性更强。且不易出错。我的目的并非为了省略这个括号,省略了并不会让事情变得更好。我所想要表达的是sizeof的还有一方面:由于如今我们知道了sizeof不是函数而是keyword,所以其本质也就全然不同了。函数是在执行时确定的,而keyword是在编译时确定的。差别的话。尝试执行例如以下程序:

    #include <stdio.h>
    
    int main()
    {
        int cc[10];
        printf("%d
    ", sizeof cc[999999999]);
        getchar();
        return 0;
    }
    
    

    上面的程序并不会出错。而是正确输出了4。

    并非由于sizeof真的去找相对于cc首地址偏移999999999个位置的那个内存,正如上文所述。sizeof在编译时确定。所以它依据cc[X]的类型来确定大小。由于sizeof没有去訪问这些地址,所以上面程序语法上没有不论什么问题,仅仅只是逻辑上来说好像没什么实际意义。你能不能想到一个能证明sizeof真的没去"执行"括号中的东西呢?事实上挺简单,试试执行例如以下代码:

    printf("%d
    ", sizeof(printf("hactrox")));
    其结果为4,并且"hactrox并没有被输出!

    没被输出说明sizeof真的没有去调用括号中的东西。可是为什么是4呢?由于sizeof是依据类型来确定的,对于printf或者是函数,sizeof以其返回值类型来确定。由于printf返回输出字符的数量。这个数量是int类型的,所以就相当于sizeof(int),所以是4。可能你还不知道printf的这个特性。试试执行下面代码:

    #include <stdio.h>
    int main()
    {
    	int num = printf("hactrox
    ");
        printf("%d
    ", num);
        getchar();
        return 0;
    }
    一个更直接的样例例如以下:

    #include <stdio.h>
    
    int fun()
    {
        printf("hactrox");
        return 5;
    }
    
    int main()
    {
        printf("%d
    ", sizeof(fun())); // 函数没有被运行,依据其返回值类型从而输出4
    
        getchar();
        return 0;
    }

    关于sizeof另一个须要注意的地方。试试在脑海中执行以下的程序。得出一个结果以后再去执行它:

    #include <stdio.h>
    
    #define SIZE_OF_ARRAY (sizeof(array) / sizeof(array[0]))
    
    int main()
    {
        int array[] = {1, 2, 3, 4, 5};
    
        for(int d = -1; d < (SIZE_OF_ARRAY-1); d++)
            printf("%d
    ", array[d+1]);
        
        printf("END
    ");
        getchar();
        return 0;
    }
    
    是不是跟你想的不太一样?为什么数组一个都没输出?原因就在于sizeof返回的是unsigned int。当int与unsigned int比較的时候,int是要转成unsigned int的,当int <0的时候,这样的强制转换自然也就悲剧了,其结果是MaxValue(unsigned int)-abs(int),那么当d = -1的时候,自然就转变成一个相当巨大的数了,for循环当然也就不运行了。

    #include <stdio.h>
    
    int main()
    {
        int a = -1;
        unsigned int b = 10000;
        if(a > b)
            printf("a > b
    ");
        else
            printf("a < b
    ");
        
        a = (unsigned int)a;
        printf("%u
    ", a);  // unsigned int要用%u输出而不要习惯地写成%d
        
        getchar();
        return 0;
    }

    最后,由于刚才提到了unsigned int的最大值。C语言中想要输出int或是unsigned int的最大值要怎么办呢?有个简单的小技巧:

    #include <stdio.h>
    
    int main()
    {
        printf("Max value of unsigned int is: %u
    ", ~(unsigned int)0);       // 结果仅仅能用%u表示
        printf("Max value of int is: %d
    ", ~(unsigned int)0 >>1);   // 结果用%d, %u表示均可 
        getchar();
        return 0;
    }
    


  • 相关阅读:
    进度条与拖动条的使用学习
    双指针,BFS和图论(三)
    dubbo文档笔记
    ByteBuf
    Netty源码解析—客户端启动
    Netty源码解析---服务端启动
    java并发程序和共享对象实用策略
    docker命令
    elasticSearch基本使用
    Filebeat6.3文档—Log input配置
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5420224.html
Copyright © 2011-2022 走看看