为啥这个 sizeof(c+a) 给出 4 字节而不是 3
Posted
技术标签:
【中文标题】为啥这个 sizeof(c+a) 给出 4 字节而不是 3【英文标题】:why this sizeof(c+a) is giving 4 byte instead of 3为什么这个 sizeof(c+a) 给出 4 字节而不是 3 【发布时间】:2017-10-12 17:35:22 【问题描述】:#include <stdio.h>
int main()
short int a;
char c;
printf("%d %d %d",sizeof(a),sizeof(c),sizeof(c+a));
在这个 sizeof a 是 2 字节 char 的大小是 1 字节,但我把它们加起来是 4 字节。它在表达式中做了什么以使其成为 4
【问题讨论】:
旁白:%d
==> %zu
这到底是怎么得到这么多票的?
是的...这很令人费解...鉴于表达式sizeof(c+a)
本身就是无意义且无用的。好吧,我想有些人只是对 OP 的结果感到惊讶。
@EugeneSh。 IMO 这实际上是一个有趣的问题,涉及整数转换规则的细微差别。如,“为什么不是输出 2?”因为副手,你会认为short + char
应该是short
,对吧?
【参考方案1】:
将short int
添加到char
会生成int
,这在您的系统上显然是4 个字节。
这是“整数提升”的情况。有关说明,请参阅In a C expression where unsigned int and signed int are present, which type will be promoted to what type?。规则相当混乱,但那里的答案很好地解释了它。
按照the C standard的6.3.1.8常用算术转换,实际转换规则为:
如果两个操作数的类型相同,则不再进行转换 需要。
否则,如果两个操作数都具有有符号整数类型或都具有 无符号整数类型,具有较小类型的操作数 整数转换等级转换为操作数的类型 排名更高。
否则,如果具有无符号整数类型的操作数具有 等级大于或等于其他类型的等级 操作数,则带符号整数类型的操作数为 转换为无符号整数的操作数类型 输入。
否则,如果带符号整数类型的操作数的类型可以 用无符号表示操作数类型的所有值 整数类型,则无符号整数类型的操作数为 转换为有符号整数类型的操作数的类型。
否则,两个操作数都将转换为无符号 与带符号的操作数类型对应的整数类型 整数类型。
结果是 4,因为正如 @WeatherVane 在 cmets 中指出的那样:
5.1.2.3 第 11 段示例 2 在执行片段时 char c1, c2; /* ... */ c1 = c1 + c2;
“整数提升”要求抽象机将每个变量的值提升为 int 大小,然后添加两个整数并截断总和。但这里没有截断,因为目的地未知。
【讨论】:
您确定它正在提升为 int 而不是 short 吗? (不是说你错了,我只是想弄清楚标准是如何规定促销的) @ChristianGibbons 如果发布的代码和输出正确,它正在被提升为int
。尽管在阅读规则时,我也认为这可能是错误的,它应该被提升为short
。这可能是编译器错误。
@ChristianGibbons a+c
尚未分配给任何目标变量。算术计算提升为int
。
这不是类型转换为另一种变量类型;没有目标变量类型。算术计算被提升为int
(以减少中间值溢出的可能性)但我不知道参考。
5.1.2.3 第 11 段示例 2 在执行片段 char c1, c2; /* ... */ c1 = c1 + c2;
“整数提升”要求抽象机将每个变量的值提升为整数大小,然后将两个整数相加并截断总和。但这里没有截断,因为目的地未知。【参考方案2】:
sizeof
在评估后返回对象表示的大小。表达式c+a
显然返回一个int,即四个字节。我认为您正在寻找的是:
sizeof(c) + sizeof(a)
【讨论】:
【参考方案3】:当char
、short int
、bool
等整数类型占用的字节数少于int
时,当对它们执行操作时,这些数据类型会自动提升为int
或unsigned int
.
C11 §6.3.1.1 布尔值、字符和整数
如果一个 int 可以表示原始类型的所有值(受限制 通过宽度,对于一个位域),该值被转换为一个 int; 否则,它将转换为无符号整数。这些被称为 整数促销。 58)
因此,c+a
被转换为 int
类型,结果具有这种常见的操作数类型,即 int
。
此外,您的代码行为是未定义,因为您使用了错误的格式说明符。
所以,请使用%zu
而不是%d
,因为sizeof()
返回size_t
而size_t
是unsigned
。
C11 标准:§7.21.6.1:第 9 段:
如果转换规范无效,则行为是 undefined. 225) 如果任何参数不是正确的类型 相应的转换规范,行为未定义。
【讨论】:
【参考方案4】:对于有数学倾向的人(因为我突然想知道这样的事情何时可能是真的):
OP 的误解是
f(x) + f(y) = f(x+y)
这对于 sizeof()
肯定不是真的,因为 Tom 在 cmets 中指出。
它为为真的函数类被称为Additive Maps
典型示例包括环、向量空间或保留加法组的模块之间的映射。
【讨论】:
很有趣,但在“C”中,sizeof 是一个编译时运算符,它们不是函数。回到抽象代数,两个“+”运算符是不同的,一个是无符号整数值,另一个是类型,所以我认为你没有映射。 @tom-blodget 是的,只是在一个愚蠢的问题上玩得开心:) 更新了答案以参考您的意见。以上是关于为啥这个 sizeof(c+a) 给出 4 字节而不是 3的主要内容,如果未能解决你的问题,请参考以下文章
为啥 sizeof() 返回 4 个字节而不是 2 个字节的 short int? [复制]
为啥c#中bool要占4个字节 32位呢 为啥不用像byte 1个字节存储呢
在 C 中,为啥 sizeof(char) 为 1,而 'a' 是 int?
在 C 中使用 sizeof 运算符分配浮点数据类型(5.0)而不是 4 个字节 [重复]
C语言 数组的问题,书上的例子,说a = sizeof(mu) / sizeof(mu[0])可以统计数组的元素个数,为啥?