C/C++ sizeof运算符:为什么sizeof('a')返回不同的值?
C/C++ sizeof运算符:为什么sizeof('a')返回不同的值?
可能是重复问题:
我是C的初学者,对此感到困惑。
C:
我尝试使用"%zu"修饰符在C中打印sizeof('a'),它打印出一个值4。
C++:
在C++中使用cout和printf(使用上述格式)打印sizeof('a'),都打印出一个值1。
我相信正确的值应该是1,因为'a'将被视为一个char。为什么C中它不返回4?这两种语言中的sizeof操作是否不同?如果是这样,有什么区别,为什么返回不同的值?
我在两种情况下都使用了gcc编译器。
在C语言中,`'a'`是一个字符常量,它被视为整数,所以得到的大小是4,而在C++中它被视为一个`char`类型。这是一个重复的问题,可以在这里找到答案:Size of character ('a') in C/C++。我曾经尝试搜索,但没有找到任何相关的问题。谢谢你让我知道这个重复问题。
-1:在C语言中,没有对整数的大小进行定义,除了与`char`和`long`的大小有关的定义。
- 如果你阅读链接的答案,你可以清楚地在第一个和唯一的答案的评论中看到`int`的`sizeof`是与平台相关的。我没有解决这个问题,因为1. 链接的帖子已经解决了这个问题,我期望一个mod来关闭这个帖子;2. 鉴于提问者的问题背景,显然他的机器上`int`的`sizeof`是4。
:这并不能改变一个事实,即许多C编程错误是由于断言`int`是4个字符而引起的,而你的回答继续传播这个错误的神话。如果你知道4是不正确的,为什么还要写上呢?我认为我们必须同意各自的观点,这是我一直以来的一个痛点。
在C语言中,字符字面值(常量)的类型为int。因此,考虑下面的程序:
#includemain(int argc, char *argv[]) { printf("%zu\n", sizeof('a')); printf("%zu\n", sizeof('ab')); printf("%zu\n", sizeof('abc')); printf("%zu\n", sizeof('abcd')); printf("%u\n", 'a'); printf("%u\n", 'ab'); printf("%u\n", 'abc'); printf("%u\n", 'abcd'); printf("%x\n", 'a'); printf("%x\n", 'ab'); printf("%x\n", 'abc'); printf("%x\n", 'abcd'); printf("%c\n", 'a'); printf("%c\n", 'ab'); printf("%c\n", 'abc'); printf("%c\n", 'abcd'); }
前四个语句都将字面值视为一个字符常量,并且它们都打印出4,即sizeof(int),至少在gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3上是这样的。请注意,这个编译器对上述程序输出了多个警告:
warning: multi-character character constant
基本上,字符字面值指定了构成一个int的四个字节,从左到右,高位字节在前。缺失的前导字节填充为0。因此,在我的机器上,第二组和第三组printf语句的输出是:
97 24930 6382179 1633837924 61 6162 616263 61626364
在十六进制输出中,你可以看到字面值中四个字符的布局(从左到右的ASCII码):'a'映射到最高位字节0x61。最后,第四组打印:
a b c d
即字符字面值被推送到栈上作为整数,但printf只打印该整数的最低字节作为字符。C++的行为类似,但一字节的字符字面值被认为是char类型,而不是int类型。下面的程序:
#includeusing namespace std; main(int argc, char *argv[]) { cout << sizeof('a') << endl; cout << sizeof('ab') << endl; cout << sizeof('abc') << endl; cout << sizeof('abcd') << endl; cout << 'a' << endl; cout << 'ab' << endl; cout << 'abc' << endl; cout << 'abcd' << endl; }
将使用GCC编译并给出类似的警告。它的输出与C语言的输出不同:
1 4 4 4 a 24930 6382179 1633837924
因此,一字节的字符字面值被视为char类型,而多字节的字面值被视为int类型。
重要提示:我在一个32位的Linux系统上运行了我的测试,其中int占用4个字节。有趣的是看看其他系统上会发生什么,比如64位的系统。
编辑:修正回答(感谢提示):字符字面值在C中的类型为int,它们不会被强制转换为int。大多数系统都有4字节的int,除了16位的系统。
小的不正确之处:字符常量不会被强制转换为int,它们在C中的类型为int。谢谢,我会修复这个问题。这意味着每次赋值时它们都会被强制转换为char。
我从未见过一个int占用64位的实现,但据我所知,最初的想法是在C中,int对应于处理器寄存器的宽度。不过,我认为在64位处理器上,char应该是8位,short应该是16位,int应该是32位,long应该是64位(对我来说,64位的int感觉有点奇怪)。
另外,我有点惊讶在小端架构上'abcd'被表示为0x61626364,我以为会是0x64636261。
64位int的问题在于你会在整数类型层次结构的较低部分有一个“间隙”,并且无法使用标准类型实现int32_t。
是的,这就是我所想的。在整数层次结构的较低部分会有一个间隙,而int、long和long long类型会重叠(除非例如long是128位,long long是256位)。