问题描述
正在访问一个非 - 常量
通过对象常量
声明C标准允许的?
例如。为保证编译及以下code符合标准的平台上输出23和42?
Is accessing a non-const
object through a const
declaration allowed by the C standard?E.g. is the following code guaranteed to compile and output 23 and 42 on a standard-conforming platform?
翻译单元答:
int a = 23;
void foo(void) { a = 42; }
翻译单元B:
#include <stdio.h>
extern volatile const int a;
void foo(void);
int main(void) {
printf("%i\n", a);
foo();
printf("%i\n", a);
return 0;
}
在ISO / IEC 9899:1999年,我刚刚发现(6.7.3条第5款):
In the ISO/IEC 9899:1999, I just found (6.7.3, paragraph 5):
如果试图修改与通过使用常量限定类型定义的对象
与非const限定类型的左值的,其行为是不确定的。
但在上述情况下,对象没有被定义为常量
(只是声明)。
But in the case above, the object is not defined as const
(but just declared).
更新
我终于找到了在ISO / IEC 9899:1999
I finally found it in ISO/IEC 9899:1999.
6.2.7,2
这指的是同一对象或函数应具有兼容类型的所有声明;
否则,行为是不确定的。
6.7.3,9
有关两个限定类型是兼容的,两者应具有相同的合格
兼容类型的版本; [...]
所以,它的是未定义的行为。
So, it is undefined behaviour.
推荐答案
恩A包含的(只)定义一个
。因此, A
真的是一个非const对象,它可以作为,例如在没有问题访问从功能。
TU A contains the (only) definition of a
. So a
really is a non-const object, and it can be accessed as such from a function in A with no problems.
我是pretty确保TU b都会调用不确定的行为,因为它的的声明中的
不定义达成一致。到目前为止,我已经找到了支持,这是最好的UB报价6.7.5 / 2:
I'm pretty sure that TU B invokes undefined behavior, since its declaration of a
doesn't agree with the definition. Best quote I've found so far to support that this is UB is 6.7.5/2:
每个声明符声明了一个鉴定网络连接器,并断言,当一个
相同的形式的说明符的操作数出现在一个前pression,
它指定一个函数或对象与范围,存储时间,
并通过特定的声明科幻器类型所指示。
下面,B中的声明中称, A
的类型挥发性const int的
。事实上,对象没有(合格)键入挥发性const int的
,它具有(资质)键入 INT
。语义冲突是UB。
Here, the declaration in B asserts that a
has type volatile const int
. In fact the object does not have (qualified) type volatile const int
, it has (qualified) type int
. Violation of semantics is UB.
在实践中究竟会发生的是,涂某将被编译,如果 A
是非常量。 TU B将被编译为如果 A
是一个挥发性const int的
,这意味着它不会缓存的价值 A
可言。因此,我希望它的工作中提供的接头没有注意到,反对不匹配的类型,因为我没有立即看到恩B如何可能可能发出code,它出了问题。然而,我的想象力的匮乏是不一样的担保行为。
In practice what will happen is that TU A will be compiled as if a
is non-const. TU B will be compiled as if a
were a volatile const int
, which means it won't cache the value of a
at all. Thus, I'd expect it to work provided the linker doesn't notice and object to the mismatched types, because I don't immediately see how TU B could possibly emit code that goes wrong. However, my lack of imagination is not the same as guaranteed behavior.
据我所知,没有什么标准说,挥发性
在文件范围内的对象不能被保存在其他对象完全不同的存储库,提供了不同的指令阅读。实施仍然必须能够通过,也就是说,一个挥发性
指针读取普通对象,所以假设为例子,正常的加载指令适用于特殊对象,它使用通过指针读取到的挥发性限定类型时。但是,如果(作为优化)发出执行特殊对象特殊指令和特殊指令的没有的工作,正常的对象,那么热潮。而且我认为这是程序员的错,虽然我承认,所以我不能完全确信它符合我只是发明了这个实施2分钟前。
AFAIK, there's nothing in the standard to say that volatile
objects at file scope can't be stored in a completely different memory bank from other objects, that provides different instructions to read them. The implementation would still have to be capable of reading a normal object through, say, a volatile
pointer, so suppose for example that the "normal" load instruction works on "special" objects, and it uses that when reading through a pointer to a volatile-qualified type. But if (as an optimization) the implementation emitted the special instruction for special objects, and the special instruction didn't work on normal objects, then boom. And I think that's the programmer's fault, although I confess I only invented this implementation 2 minutes ago so I can't be entirely confident that it conforms.
这篇关于Ç - 访问通过常量声明一个非const的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!