我已经考虑过了。 这就是代码:
#define IP_VAL(id) ({ \
char ip[32] = {0}; \
sprintf(ip,"192.168.0.%d",id&0xff); \
(char *)ip; \
})
它确实有效,但我想知道宏是否会引起问题?
我这样用过:
function(IP_VAL(id));
但我不确定它是否绝对正常。 ip[32]
是否超出了行动范围?
非常感谢您编辑我的问题:)
我测试了这样一个简单的例子:
main(){
int a = 1;
int b = 2;
a = b;
a = ({
int c = 3;
c;
});
a = ({
int d = 4;
d;
});
a = ({
int c = 5;
c;
});
({
int c = 6;
c;
});
({
int c = 7;
c;
});
({
int c = 8;
c;
});
}
然后objdump:
080483ed <main>:
80483ed: 55 push %ebp
80483ee: 89 e5 mov %esp,%ebp
80483f0: 83 ec 20 sub $0x20,%esp
80483f3: c7 45 e0 01 00 00 00 movl $0x1,-0x20(%ebp)
80483fa: c7 45 e4 02 00 00 00 movl $0x2,-0x1c(%ebp)
8048401: 8b 45 e4 mov -0x1c(%ebp),%eax
8048404: 89 45 e0 mov %eax,-0x20(%ebp)
8048407: c7 45 e8 03 00 00 00 movl $0x3,-0x18(%ebp)
804840e: 8b 45 e8 mov -0x18(%ebp),%eax
8048411: 89 45 e0 mov %eax,-0x20(%ebp)
8048414: c7 45 ec 04 00 00 00 movl $0x4,-0x14(%ebp)
804841b: 8b 45 ec mov -0x14(%ebp),%eax
804841e: 89 45 e0 mov %eax,-0x20(%ebp)
8048421: c7 45 f0 05 00 00 00 movl $0x5,-0x10(%ebp)
8048428: 8b 45 f0 mov -0x10(%ebp),%eax
804842b: 89 45 e0 mov %eax,-0x20(%ebp)
804842e: c7 45 f4 06 00 00 00 movl $0x6,-0xc(%ebp)
8048435: c7 45 f8 07 00 00 00 movl $0x7,-0x8(%ebp)
804843c: c7 45 fc 08 00 00 00 movl $0x8,-0x4(%ebp)
8048443: c9 leave
8048444: c3 ret
所以我认为&#39; c&#39;并且&#39; d&#39;就像&#39; a&#39;和&#39; b&#39;,它们是&#39; main()&#39;堆栈中的变量。不同之处在于它们的范围。在示例中,每个&#39; c&#39;有不同的地址。
我认为宏观&#39; IP_VAL&#39;有效,但我不知道gcc编译选项是否会影响它?
答案 0 :(得分:2)
这不是标准C而是gcc扩展。它没有得到安全使用。
ip
数组的生命周期仅限于声明它的范围。您将指向此数组的指针返回到statement-expression的外部,其中数组不再存在。有些人认为,生命周期是完整表达的持续时间,但GCC文档中没有任何内容似乎支持这种说法。取消引用此指针可能会产生任何结果。它似乎完全符合运气。
将数组声明为static
将解决问题,但是静态本地数组允许您编写一个不依赖于gcc扩展的简单函数。
解决问题的另一种方法如下:
#define IP_VAL(id) \
( \
( \
{ \
struct { char ip[32]; } p; \
sprintf (p.ip, "192.168.0.%d", id&0xff); \
p; \
} \
).ip \
)
此版本没有指向任何潜在过期局部变量的指针。