我正在使用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
,我会得到结果,对吗?
从上面的代码中可以看出,%c
将int
的后8位解码为一个字符,为什么%d
不能这样做(即,解码后32位size_t
变量的内容是int
的位数吗?我相信如果这样做,我们可以得到足够少的相同结果,这就是我最初问这个问题时的意思。 。
答案 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));