具有常量表达式的初始化程序可能在C99中溢出

这是有效的C99代码吗?如果是这样,它是否定义了实现定义的行为?

int a;
unsigned long b[] = {(unsigned long)&a+1};

根据我对C99标准的理解,根据ISO C99标准的§6.6,这可能是有效的:

  1. 整数常量表达式应具有整数类型,并且仅应具有整数常量的操作数(...)整数常量表达式中的强制转换运算符只能将算术类型转换为整数类型,除非作为操作数的一部分转换为sizeof运算符。

  2. 初始化程序中的常量表达式允许更大的自由度。这样的常数表达式应为以下之一或求值:

    • 算术常数表达式
    • (...)
    • 一个对象类型的地址常量,加上或减去一个整数常量表达式。

但是,由于存在加法溢出的可能,因此这可能不被视为常量表达式,因此不是有效的C99代码。

有人可以确认我的推理是否正确吗?

请注意,即使使用,GCC和Clang都接受此代码而不会发出警告-std=c99 -pedantic但是,当强制转换为unsigned int而不是时unsigned long,即使用以下代码:

int a;
unsigned long b[] = {(unsigned int)&a+1};

然后,两个编译器都抱怨该表达式不是编译时常量。

沙菲克·雅格莫(Shafik Yaghmour)

来自这个clang开发人员线程的一个类似问题是:当转换为long但不是int时,函数指针是编译时常量吗?其理由是该标准不需要编译器支持此方法(此方案未包含在中的项目符号中6.6p7),尽管允许该方法支持该支持的截断地址将很麻烦:

我假设您的目标上的sizeof(int)<sizeof(void(*)())== sizeof(long)问题在于,工具链几乎可以肯定不能将截断的地址表示为重定位。

C仅要求实现支持以下初始化程序值:(1)常量二进制数据,(2)某个对象的地址,或(3)或添加到某个对象地址的偏移量。我们被允许(但不是必需)支持更深奥的事情,例如减去两个地址或将一个地址乘以一个常数,或者,如您所愿,将地址的高位截断。这种计算需要从汇编器到装载器的整个工具链的支持,包括一路走来的各种文件格式。该支持通常不存在。

您的案例(将指针转换为整数类型)不符合6.6段落下的任何案例7

初始化程序中的常量表达式允许更大的自由度。这样的常数表达式应为以下之一或求值:

  • 算术常数表达式
  • 指针指针常量,
  • 地址常数,或
  • 一个对象类型的地址常量,加上或减去一个整数常量表达式。

但是如后编译器中所述,允许其支持其他形式的常量表达式:

一个实现可以接受其他形式的常量表达式。

但既不接受clang也不gcc接受。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

索引字符串文字是初始化程序常量表达式吗?

用于double类型的静态类成员的常量表达式初始化程序

常量表达式中带有未初始化成员的“默认”构造函数

初始化程序列表中的非常量表达式不能从类型'int'缩小为'unsigned long long'

GLSL:由于非常量表达式初始化,For循环中出现错误

如果C ++中的数组要求的大小是一个常量表达式,为什么我可以使用仅带有const的变量来对其进行初始化?

'this'不能在带有this->指针变量的常量表达式错误(C ++)中使用

“函数调用必须在常量表达式中具有常量值”

使用boost :: assign :: list_of进行声明时,不能由非常量表达式初始化

是否有可能在C ++中,const变量的初始化延迟,像Java的“空白最终”功能?

指定的初始化程序可以合法地引用它在C99中初始化的变量吗?

在c99中初始化布尔数组的方法

在 C# 中创建常量表达式

带有表达式的C ++初始化列表

将编译时定义的大小的数组初始化为常量表达式

飞镖:常数评估错误。方法“ []”不能在常量表达式中调用

f#中的参数化测试-这不是有效的常量表达式

将表达式传递给初始化程序

为什么只有自动实现的属性才能在C#中具有初始化程序?

使用表达式树初始化具有任意数量属性的新匿名对象

如何修复“[something] 可能在此函数中未初始化使用”警告?

是否有可能在{0,1}上对这些对称表达式进行表示

是否有可能在python中提示输入已编译的正则表达式?

C99结构指定的初始化程序和其他价值

C99指定的初始化程序还是CGMake宏?

常量表达式中的模板化委派副本构造函数

带lambda表达式的invokeAndWait在静态初始化程序中永久挂起

错误:typedef表达式中“ COUNT_TYPE”之前的预期初始化程序

在宏中检测整数常量表达式