为什么现在"{static const char a [] = {...}"和"{static const char a [] = {...}"和"{const char a [] = {...}"? [英] Why is there now a difference between "{static const char a[]={...}" and "{const char a[]={...}"?

查看:93
本文介绍了为什么现在"{static const char a [] = {...}"和"{static const char a [] = {...}"和"{const char a [] = {...}"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看看 C代码 gcc的早期版本将a()和c()都编译为两条指令,即加载z的地址,然后跳转到b.

Earlier versions of gcc compiles both a() and c() to two instructions, load address of z, jump to b.

所有现代编译器我都尝试过模拟" a()来制作堆栈框架,将z复制到堆栈上,调用b,拆除堆栈框架,但是将c()保留为两条指令的简单版本.

All modern compilers I tried "pessimise" a() to "make stack frame, copy z onto stack, call b, tear down stack frame, but leave c() as the two instruction simple version.

实际上什么都没有改变,实际上在这种情况下,现代编译器现在变慢了.....

In effect nothing has changed, in practice modern compilers are now slower for this use case.....

有人知道为什么吗?

推荐答案

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

这篇关于为什么现在"{static const char a [] = {...}"和"{static const char a [] = {...}"和"{const char a [] = {...}"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆