【问题标题】:int is 4 bytes but still it can be stored in char why is there no overflowint 是 4 个字节,但它仍然可以存储在 char 中,为什么没有溢出
【发布时间】:2011-06-19 05:28:43
【问题描述】:

看看这个程序

#include<stdio.h>

int main (){

char c='a';
printf("%d %d", sizeof(c),sizeof('a'));
}

输出是1 4
我知道当我们写一个语句 char c='a';

那么在 1 字节 (char c) 的空间中如何存储一些 4 字节 (ASCII 码) 的东西,为什么没有溢出等。

【问题讨论】:

  • 奇怪的是,sizeof('a') 是 C 和 C++ 之间的差异之一(因此后者不是前者的严格超集):在 C 中,sizeof('a') == sizeof(int),在 C++ 中,sizeof('a') == sizeof(char) == 1 .

标签: c


【解决方案1】:

首先,根据 ANSI/IEC 9899:1999(E) §6.4.4.4:

10. 整数字符常量的类型为 int。整数字符常量的值 包含映射到单字节执行字符的单个字符是 被解释为整数的映射字符表示的数值。 [...]

§6.5.3.4:

2. sizeof 运算符产生其操作数的大小(以字节为单位),可能是 表达式或类型的括号名称。大小由类型决定 操作数。 [...]

 3. 当应用于具有 char、unsigned char 或 signed char 类型的操作数时, (或其合格版本)结果为 1。 [...]

如您所见,由于字符常量的类型是int,对于sizeof('a'),我们得到sizeof(int),在您的平台上是4。然而,对于sizeof(c),我们得到char 的大小,它被定义为1。

那么为什么我们可以将'a' 分配给char

§6.5.16.1:

 2. 在简单赋值 (=) 中,将右操作数的值转换为赋值表达式的类型,并替换左操作数指定的对象中存储的值。

因此,int'a' 被隐式转换为 char。里面也有一个例子,明确显示ints 可以隐式转换为char

【讨论】:

  • 如果你想真的迂腐,也可以引用6.3.1.3/1,“如果值可以用新类型表示,它是不变的”,和6.2.5/3,“char 足够大,可以存储基本执行字符集的任何成员”,以及 5.2.1/3“基本执行字符集应具有……拉丁字母的 26 个小写字母" :-)
【解决方案2】:

编译器将int 隐式转换为char

int i = 42;
char c = i * 2 - 4;

编译器将最后一行解释为:

char c = (char)(i * 2 - 4);

这些implicit type conversions 由编译器处理 - 没有“缓冲区溢出”。 (char) 是在内部处理的(很可能由机器本身处理,对于像 int 这样的简单类型)。它适当地减少了额外的字节并保留了“签名”(+/-)。

【讨论】:

  • preserves the "signedness (+/-)."是什么意思请详细说明
  • @AbhishekMane 我猜我指的是two's complement。例如,-1 的二进制表示对于 intchar 是不同的。事实上,(int)(-1) == 0b11111111111111111111111111111111,而(char)(-1) == 0b11111111。 C 与字节序(字节顺序)一起为您处理这个问题。诚然,负整数之间的转换与正整数的转换相同——大端顺序取最后一个字节。
  • 0b 中的 0b11111111 是什么?
【解决方案3】:

“字符文字的类型为 int”(http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7l.doc%2Flanguage%2Fref%2Fclrc02ccon .htm)

但是 C 允许您进行理论上“不安全”的自动转换——例如,可以这样做,

char c = 34;

即使 34 显然是一个 4 字节的 int。使这个安全的原因是,当你写 'a' 时,你知道它实际上是 1 个 ascii 字符,因此是 1 个字节。

顺便提个问题——让我有点困惑。

【讨论】:

    猜你喜欢
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 2017-06-08
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多