为什么const指针差异不能用作静态变量的初始化程序?

克里斯蒂安·亚历山德鲁·马卡拉斯库(Cristian Alexandru Macarascu):

编译以下C代码(使用MSVC):

char * const p1;
char * const p2;
static size_t sz = p2 - p1;

导致sz定义出现“初始化程序不是常数”错误。

由于指针是const(也尝试过数组,同样的错误),为什么diff指针不是恒定的?

埃里克(Eric Postpischil):

根据C 2018 6.6 7,对于初始化程序中使用的常量,C标准仅要求实现支持完整对象类型加或减整数常量表达式算术常量表达式空指针常量地址常量地址常量这些都不包括两个地址的减法,如下面的定义所示。

AC实现可能能够解决两个相同类型的符号地址的减法问题,尤其是如果编译器可以看到将它们放置在同一程序段中,并且C标准允许实现就可以这样做。但是,该标准不需要C实现来支持这一点,这至少部分是因为两个符号的减法可能涉及各种困难。一种是两个符号可能引用不同程序段中的对象,例如一个在恒定的只读段中,而另一个在未初始化的数据段中。编译器无法知道这些部分之间的相对差异,因为它取决于链接到程序中的其他对象模块的贡献,对象模块格式可能不支持将这种差异表示为链接器要解决的任何方式。即使在一个区域内,某些对象模块和符号方案也可以使链接器重新排列内容,以优化对齐问题。

根据6.6 8:

一个算术常量表达式应具有算术类型和应仅具有是积分常数,浮点常量,枚举常数,字符常数,操作数sizeof表达式,其结果是积分常数,和_Alignof表达式。算术常数表达式中的强制转换运算符只能将算术类型转换为算术类型,除非作为操作数的一部分sizeof或或_Alignof

根据6.6 9:

一个地址常量是一个空指针,一个指向一个左值指定静态存储持续时间,或指针的功能指示符的对象; 它应使用一元运算&符或强制转换为指针类型的整数常量显式创建,或通过使用数组或函数类型的表达式隐式创建。数组下标[]和成员访问.->运算符,地址&和间接*一元运算符以及指针强制转换可用于创建地址常量,但是不得使用这些运算符来访问对象的值。

根据6.3.2.3 3:

值为0的整数常量表达式或转换为类型的表达式void *称为空指针常量。…

根据6.6 6:

一个整数常量表达式应具有整数型和应仅具有是积分常数,枚举常数,字符常数,sizeof表达式其结果是积分常数,操作数_Alignof的表达式,和浮动常量是铸件的立即操作数。整数常量表达式中的强制转换运算符只能将算术类型转换为整数类型,除非作为sizeofor _Alignof运算符的一部分。

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我们不能用从类型变量未初始化的局部变量访问静态内容?

为什么一个静态变量的一个方法调用返回另一个静态变量保持为空初始化?

静态变量初始化java

静态变量何时初始化?

静态变量初始化?

在构造函数中初始化静态变量时,为什么Java不给出错误?

如何初始化静态变量

为什么在类外部用静态变量的重新声明来初始化静态变量?我们不能只初始化它而不是重新声明它吗?

为什么在这里允许使用非const初始化静态变量?

静态变量初始化测验

为什么不能用括号括起来的初始化程序列表构造gsl :: span

静态变量的初始化

在C语言中,为什么不能将const变量用作数组大小的初始化程序?

为什么非常数静态变量需要在类外部初始化?

重新初始化静态变量

为什么要在声明静态变量之前对其进行初始化

使用类模板的const静态变量初始化数组大小时出错

为什么未初始化模板类的嵌入式静态变量?

为什么在用指针编译时不能分配const初始化

静态变量初始化过程

静态变量本身的初始化

为什么不能用其他静态const指针初始化静态const指针?

为什么我们不能在构造函数初始化列表中初始化静态变量,但可以在构造函数主体中初始化

为什么不能用其他变量的值初始化静态变量?

PHP为什么不能将静态变量初始化为time()?

为什么超类中的静态块/静态变量在main之前初始化?

在静态构造函数中初始化静态变量而不是直接赋值的好处是什么?

为什么我不能用 nullptr 初始化一个自动推导的指针?

为什么智能指针类型的成员变量不能在类的声明处初始化?