sizeof()运算符的输出数据类型

时间:2019-01-31 15:15:54

标签: c ubuntu ubuntu-16.04 sizeof gcc5

我正在使用Ubuntu 16.04.5和GCC版本5.4.0。

我正在和sizeof()运算符一起玩,编写了以下代码:

#include <stdio.h>

int main(int argc, char *argv[]){

        long int mylint = 31331313131.1313;

        printf("size of long int is %d\n", sizeof(mylint));
        printf("size of long int is %d\n", sizeof(long int));

        return 0;
}

我尝试使用gcc -o ... ...命令进行编译,并且期望:

size of long int is 8
size of long int is 8

但是我遇到了以下错误:

fl_double_lint.c: In function ‘main’:
fl_double_lint.c:11:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]

  printf("size of long int is %d\n", sizeof(mylint));
         ^
fl_double_lint.c:12:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
  printf("size of long int is %d\n", sizeof(long int));

当我使用%ld时,它可以正常工作。为什么sizeof()%d不兼容? (为什么是“ long unsigned int”而不是“ int”?)

编辑:我知道,关于sizeof()运算符的输出,已经提出了很多问题(如注释中所建议)。但是,他们没有回答为什么使用%d不起作用(即不给出任何结果)的问题。我知道这是不正确的格式,但是只要我们使用char有一个%d类型的变量,我们就可以得到等效的int结果,简而言之,uint8_t,uint16_t,uint32_t也是如此(通常用于等于或小于32位的类型)。以下代码有效:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[]){

        char mychar = 'd';
        uint32_t myuint32 = 32;
        uint16_t myuint16 = 16;
        uint8_t myuint8 = 8;
        short myshort = 26945;
        int myint = 100;

        printf("integer equivalent of mychar is %d\n", mychar);
        printf("integer equivalent of myuint8 is %d\n", myuint8);
        printf("integer equivalent of myuint16 is %d\n", myuint16);
        printf("integer equivalent of myuint32 is %d\n", myuint32);
        printf("character equivalent of myint is %c\n", myint);
        printf("integer equivalent of myshort is %d\n", myshort);


        return 0;
}

结果是:

integer equivalent of mychar is 100
integer equivalent of myuint8 is 8
integer equivalent of myuint16 is 16
integer equivalent of myuint32 is 32
character equivalent of myint is d
integer equivalent of myshort is 26945

现在我发现%d对于需要存储大于32位的任何变量都不起作用。考虑了this question之后,我对size_t的实现依赖性有了一些了解,也许在我的系统中是unsigned long%ld也给出了结果证明)。因此,如果size_t是我系统中的unsigned int,我会得到结果,对吗?

从上面的代码中可以看出,%cint的后8位解码为一个字符,为什么%d不能这样做(即,解码后32位size_t变量的内容是int的位数吗?我相信如果这样做,我们可以得到足够少的相同结果,这就是我最初问这个问题时的意思。 。

1 个答案:

答案 0 :(得分:24)

sizeof运算符求值为类型size_t的值。此类型是无符号的,通常大于int,这就是收到警告的原因。

printf使用错误的格式说明符会调用undefined behavior。但是,由于C标准6.3.1.1p2中的整数促销规则,对于小于int的类型,您可以避免使用此方法:

  

以下表达式可以在表达式中使用int或unsigned   可以使用int:

     
      
  • 具有整数类型(小于int或unsigned int)的整数转换等级小于的对象或表达式   或等于int和unsigned int的等级。
  •   
  • 一个类型的位域   _Bool,int,signed int或unsigned int。
  •   
     

如果int可以表示原始类型的所有值(受宽度限制,   对于位字段),该值将转换为int;除此以外,   它被转换为unsigned int。这些被称为   整数促销。所有其他类型均未更改   整数促销。

只要这不会导致从无符号更改为有符号,可以使用int打印小于%d的类型。

根据C standard的第7.21.6.1p7节中有关size_t函数的长度修饰符的规定,%zu的正确类型修饰符为fprintf(并通过扩展, printf):

  

z

     

指定以下d,i,o,u,x或X转换   说明符适用于size_t或相应的带符号整数   类型参数或以下n个转换说明符适用   指向与size_t对应的有符号整数类型的指针   论点。

所以您想要的是:

printf("size of long int is %zu\n", sizeof(mylint));