c-GCC声明表达式问题



我刚刚读到GCC中的语句表达式扩展,在使用它时发现了一些意外行为。

请注意这个例子:

#include <stdio.h>
int main(void)
{
    char* res1 = ({
                        char arr[] ={'h', 'e', ''}; // was char *arr[]
                        arr[0] = 'x';
                        char* ptr = arr;
                        ptr;
                 });

    char* res2 = ({
                        char arr[] ={'h', 'e', ''}; // was char *arr[]
                        arr[0] = 'X';
                        char* ptr = arr;
                        ptr;
                 });
    printf ("%s %pn", res1, res1);
    printf ("%s %pn", res2, res2);
    return 0;
}

输出:

X 0x7fff93098160
X 0x7fff93098160

我注意到,第一块中的变量arr和第二块中的arr采用相同的存储器地址。

为什么会这样??

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

char* res1;
{
  char arr[] ={'h', 'e', ''};
  arr[0] = 'x';
  char* ptr = arr;
  res1 = ptr;
}
char* res2;
{
  char arr[] ={'h', 'e', ''};
  arr[0] = 'X';
  char* ptr = arr;
  res2 = ptr;
}
printf ("%s %pn", res1, res1);
printf ("%s %pn", res2, res2);

arr的两次出现都是具有自动存储持续时间的数组对象;它们对于语句表达式内的封闭块CCD_ 5是局部的。

每个语句表达式获取该局部变量的地址;该地址保存在CCD_ 6中,并且res2 CCD_。

这与返回局部变量地址的函数的问题相同。当变量不存在,并且程序的行为未定义时,地址将变为无效。

所以不要那样做。

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

如果您要访问或使用这些指针的值,您将调用未定义的行为,因此它们的相等性无关紧要。

最新更新