为啥 sizeof 表达式不是像 2、4、8 等这样的编译时常量?

Posted

技术标签:

【中文标题】为啥 sizeof 表达式不是像 2、4、8 等这样的编译时常量?【英文标题】:Why is the sizeof expression not a compile-time constant like 2, 4, 8, etc.?为什么 sizeof 表达式不是像 2、4、8 等这样的编译时常量? 【发布时间】:2013-09-12 02:01:32 【问题描述】:

我的编译器是最新的 VC++ 2013 预览版。

int main()

    __declspec(align(4))           int n1 = 0; // OK.
    __declspec(align(sizeof(int))) int n2 = 0; // error C2059: syntax error : 'sizeof'

为什么 sizeof 表达式不是像 2、4、8 等那样的编译时常量?

【问题讨论】:

它说“语法错误”,所以解析器可能需要一个数字常量。在我的 unix 机器上“int a[sizeof(int)];”在全局级别编译正常。 __declspec 的东西是 MSVC 特定的扩展语法,它们有一组 nebulous rules,显然,它不受标准规则的约束。从这个意义上说,我认为sizeof() 是否是编译时常量并不重要,因为我认为这些扩展是在编译的其余部分之外处理的(即,介于 MACRO 和适当的 C++ 之间的东西构造)。简而言之,MSVC在这里制定了自己的规则,你只需要忍受它们,如果它不喜欢sizeof(),那你就不能在那里使用它。 看来 MS 定义了 __alignof 运算符正是为了您想要的目的。对于简单类型,它类似于sizeof,但对于结构等复杂类型,它的行为有些不同... AFAICT 甚至 __declspec(align(4u)) 也是不允许的。这也是相当稳定的。 【参考方案1】:

而不是问: 为什么 sizeof 表达式不是像 2、4、8 等那样的编译时常量?

(因为实际上,它 就像那些示例一样的编译时常量。(:从较新的 C 标准中禁止可变长度数组,它必须是运行时表达式:))

最好问: 为什么align(...) 不接受像 sizeof 表达式这样的编译时间常数?

Microsoft 定义 __declspec(align(#)) 只接受一小组值: 见:https://msdn.microsoft.com/en-us/library/83ythb65.aspx

"# 是对齐值。有效条目是从 1 到 8192(字节)的 2 的整数幂,例如 2、4、8、16、32 或 64。"

因此,即使使用简单的常量,也不允许任何值。 __declspec(align(7)) 是不允许的,因为它不是 2 的幂。甚至像 __declspec(align(4+4)) 这样的简单表达式也是不允许的。

【讨论】:

【参考方案2】:

在 C 标准中

sizeof 运算符不应应用于具有 函数类型或不完整类型,到括号中的此类名称 一个类型,或者一个指定位域成员的表达式。这 _Alignof 运算符不得应用于函数类型或不完整类型。

sizeof 运算符产生其操作数的大小(以字节为单位),即 可以是表达式或类型的括号名称。尺寸是 由操作数的类型决定。结果是一个整数。如果 操作数的类型是变长数组类型,操作数 被评估;否则,不计算操作数并且结果 是一个整数常量。

【讨论】:

这对这里有什么帮助?我们甚至不是在谈论 C,而是在谈论 C++,问题来自一些 MSVC 扩展而不是标准。

以上是关于为啥 sizeof 表达式不是像 2、4、8 等这样的编译时常量?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 sizeof(c+a) 给出 4 字节而不是 3

为啥 sizeof 被认为是运算符?

为啥c#中bool要占4个字节 32位呢 为啥不用像byte 1个字节存储呢

初始C语言,strlen函数和sizeof关键字的使用

c语言中,为啥在64位系统中long跟指针的大小是8,而32位的却是4?是啥导致不一样?求详细解答

数组与文字