我刚刚读到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_。
这与返回局部变量地址的函数的问题相同。当变量不存在,并且程序的行为未定义时,地址将变为无效。
所以不要那样做。
这两个数组都是语句表达式的本地数组,它们占用的内存可以在表达式结束后重用。在这种情况下,它被重用。
如果您要访问或使用这些指针的值,您将调用未定义的行为,因此它们的相等性无关紧要。