更新时间:2023-10-24 15:20:22
C ++具有以下规则:
除非对象是位域或大小为零的子对象,否则该对象的地址为其所占据的第一个字节的地址.两个生命周期重叠的对象(不是位域),如果一个对象嵌套在另一个对象中,或者至少一个对象是零大小的子对象,并且它们的类型不同,则它们可能具有相同的地址;否则,它们具有不同的地址并占用不相交的存储字节.
Unless an object is a bit-field or a subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a subobject of zero size and they are of different types; otherwise, they have distinct addresses and occupy disjoint bytes of storage.
现在,查看以下代码:
#include <stdio.h>
void c();
void b(const char *a) {
static const char *p = 0;
if (!p) {
p = a;
c();
} else {
if (a==p) {
printf("problem!\n");
}
}
}
void c() {
const char a[] = { 0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf };
b(a);
}
int main() {
c();
}
此处, c
被递归调用一次,因此根据规则,数组 a
在每个递归级别中应具有不同的地址. b
在第一次调用时存储 a
,并在第二次调用时检查是否相同.使用兼容的编译器,它不应显示问题!".但是实际上,对于旧的编译器(GCC 4.1,clang 6.0),它会显示问题!",因此这些编译器违反了该标准.
Here, c
is called recursively once, so according to the rule, the array a
should have different addresses in each recursion level. b
stores a
at the first invocation, and at the second invocation, it checks whether it is the same or not. With a conforming compiler, it should not print "problem!". But actually, with an old compiler (GCC 4.1, clang 6.0), it prints "problem!", so these compilers violate the standard.
A compiler is allowed to make a
static only in the case that it can be proven that this change is not observable:
在假设"规则下,如果程序无法观察到差异,则允许实现将两个对象存储在同一机器地址或根本不存储对象
Under the "as-if" rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference