2012-01-14 45 views
3

我刚刚阅读了关于GCC中的Statement Expressions Extension,并且在使用它时发现了一些意想不到的行为。GCC声明表达问题

请注意本实施例中:

#include <stdio.h> 

int main(void) 
{ 

    char* res1 = ({ 
         char arr[] ={'h', 'e', '\0'}; // was char *arr[] 
         arr[0] = 'x'; 
         char* ptr = arr; 
         ptr; 
       }); 


    char* res2 = ({ 
         char arr[] ={'h', 'e', '\0'}; // was char *arr[] 
         arr[0] = 'X'; 
         char* ptr = arr; 
         ptr; 
       }); 

    printf ("%s %p\n", res1, res1); 
    printf ("%s %p\n", res2, res2); 

    return 0; 
} 

输出:

X 0x7fff93098160 
X 0x7fff93098160 

我注意到的是,在第二块中第一块中的变量arrarr取相同的存储器地址。

为什么会这样呢?

回答

2

两次出现的arr都是具有自动存储持续时间的数组对象;它们在语句表达式内的封闭块{ ... }本地。

每个语句表达式抓取该局部变量的地址;该地址保存在res1和res2 and used *after* the end of the block, when the object arr` 不再存在

这与返回局部变量地址的函数相同。当变量不存在时,地址变为无效,程序的行为是不确定的。

所以不要这样做。

+0

对不起,我复制并粘贴了不正确的代码,我修改了它。 – 2012-01-14 22:08:13

+0

我编辑了我的答案,因为更正的代码现在在问题中,因此不再需要。 – 2012-01-15 04:31:25

+0

是否有任何参考文档来确认存储时间是自动的,而不是其他内容,如完整表达式的结尾? [出现在这个问题](http://stackoverflow.com/questions/40486940/declare-an-array-in-gcc-statement-expression-and-return-a-pointer-to-it)。海湾合作委员会官方文档页面没有说。 – 2016-11-08 12:52:46

3

据我所知,在语句表达式中定义的变量范围就是这些语句表达式本身。也就是说,当初始化res1时,该数组已经超出范围,并且指针指向未分配的内存。第二个语句表达式中的数组恰好占用相同的内存。它实际上没有太大的不同,从下面的代码:

char* res1; 
{ 
    char arr[] ={'h', 'e', '\0'}; 
    arr[0] = 'x'; 
    char* ptr = arr; 
    res1 = ptr; 
} 

char* res2; 
{ 
    char arr[] ={'h', 'e', '\0'}; 
    arr[0] = 'X'; 
    char* ptr = arr; 
    res2 = ptr; 
} 

printf ("%s %p\n", res1, res1); 
printf ("%s %p\n", res2, res2); 
2

两个阵列都是本地的语句表达式,它们占据内存可以表达结束后可重复使用。在这种情况下,它重用。

如果你要访问或使用这些指针的值,你会调用未定义的行为,所以它们的相等性是没有意义的。