且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为什么现在"{static const char a [] = {...}"和"{static const char a [] = {...}"和"{const char a [] = {...}"?

更新时间: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