为什么在引用int变量的大小时必须使用%ld?

时间:2015-08-16 16:10:52

标签: c printf

我像这样定义一个int:

int a;

当我想查询此int的大小时,我必须使用格式说明符%ld,如下所示:

printf("int size is %ld\n", sizeof(a));

当我使用%d作为格式说明符时,出现以下错误:

foo.c:7:10: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
    printf("int size is %d\n", sizeof(a));

问题是,当函数的参数是int时,为什么sizeof()的结果被定义为long unsigned int?

5 个答案:

答案 0 :(得分:7)

sizeof(anything)的类型是size_t,这是一些无符号整数常量。要打印它,您应该使用%zu

答案 1 :(得分:5)

根据C标准(6.5.3.4 sizeof和alignof运算符)

  

5两个运算符的结果值是实现定义的,   它的类型(无符号整数类型)是 size_t ,定义于   <stddef.h>(以及其他标题)。

和(7.19通用定义<stddef.h>

  

size_t,它是无符号整数类型的结果   sizeof运营商;

和(7.21.6.1 fprintf函数)

  

z 指定以下d,i,o,u,x或X转换说明符   适用于 size_t ....

因此写出

会更正确
printf( "int size is %zu\n", sizeof( a ) );
                     ^^^

运算符sizeof应用于哪种类型的对象并不重要。它返回给定类型的对象占用的字节数,返回的数字类型为size_t

您的编译器会发出警告,因为系统类型size_t的定义类似于unsigned long int,但您使用的是signed int。当您使用格式说明符%ld时似乎不会发出警告,因为签名的long int类型的等级等于对应于size_t的无符号long int类型的等级。

答案 2 :(得分:3)

  

“当函数的参数是int?”

首先,sizeof是一个操作员,而不是一个功能。

其次,为什么你认为它的结果类型应该与它的参数类型相同?如果你想获得结构的大小怎么办?还是阵列?还是一个指针?如何将结构的大小作为结构产生?它没有意义。

它产生一个大小,因此其结果类型为size_t,您应使用%zu进行打印。

答案 3 :(得分:2)

sizeof给出操作数占用的存储单元数。结果类型为size_t,这是一个宽度足以表示系统能够存储的最大对象大小的无符号类型。操作数的类型不会影响结果的类型。

使用C89编译器,您可以使用size_t打印%ld值并将参数转换为unsigned long

 printf( "sizeof x = %ld\n", (unsigned long) sizeof x );

使用C99及更高版本的编译器,使用%zu

 printf( "sizeof x = %zu\n", sizeof x );

答案 4 :(得分:0)

%zu不可携带;它需要一个C99库。例如,MinGW:

$ cat zu.c
#include <stdio.h>

int main(void)
{
  printf("%zu\n", sizeof (int));
  return 0;
}

$ gcc zu.c -o zu

$ ./zu.exe
zu

糟糕!字面上打印的字符zu,忽略了size参数。

对于您知道相当小的打印类型,请将大小调整为intunsigned,并使用%d%u转换说明符:

printf("sizeof int == %d\n", (int) sizeof (int));

如果对象的大小可能不适合int类型,请尝试unsigned long int:

printf("sizeof int == %lu\n", (unsigned long) sizeof object);

这可能仅在具有小int的系统(例如16位)上是必需的,这样int仅上升到32767并且unsigned int到65535,但是可能存在对象其大小超过这些值。

如果您确定该程序只需要可移植到支持C99的目标,那么%zu就是。