我刚刚阅读了GCC中的Statement Expressions Extension,我在使用它时发现了一些意想不到的行为。
请注意这个例子:
#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
我注意到,第一个块中的变量arr
和第二个块中的arr
使用相同的内存地址。
为什么会发生这种情况?
答案 0 :(得分: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);
答案 1 :(得分:2)
两个数组都是语句表达式的本地数组,并且它们占用的内存可以在表达式结束后重用。在这种情况下, 重复使用。
如果您要访问或使用这些指针的值,您将调用未定义的行为,因此它们的相等性无关紧要。
答案 2 :(得分:2)
arr
的两次出现都是具有自动存储持续时间的数组对象;它们位于语句表达式中的封闭块{ ... }
的本地。
每个语句表达式都会获取该局部变量的地址;该地址已保存在res1
且res2 and used *after* the end of the block, when the object
arr` 不再存在。
这与返回局部变量地址的函数相同。当变量不再存在时,地址变为无效,并且程序的行为未定义。
所以不要这样做。