“重新定义”语句表达式中的变量是否安全?

时间:2012-04-27 12:44:20

标签: c gcc c99 gnu99

我的问题是关于statement expressions,它是作为GNU C中的扩展添加的。请考虑以下代码:

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int i = 0;
    printf("%d\n", i);

    {int i = 1;printf("%d\n", i);}

    printf("%d\n", i);
    return EXIT_SUCCESS;
}

编译(gcc -Wall -std=gnu99 lala.c -o lala)并且正在运行将产生:

0
1
0

这种做法(扩展的使用)相当普遍,特别是在Linux内核的container_of中:

#define container_of(ptr, type, member) ({ \
                const typeof( ((type *)0)->member ) *__mptr = (ptr); 
                (type *)( (char *)__mptr - offsetof(type,member) );})

与此情况类似,我想定义一个声明局部变量并对其执行某些操作的宏。但是,我想这样做而不会污染当前范围内可用的变量名称,并避免可能的重新定义。我无法在文档中找到有关重新定义情况下确定范围的确切信息。

在上面的情况中,编译器没有发出有关重新定义的警告。我的问题是,我是否可以依赖于语句表达式中作用域的变量不会影响外部作用域中同名变量的事实?

2 个答案:

答案 0 :(得分:2)

当然这是安全的,这就是范围的制作。

(正如dreamlax在他的评论中指出的那样,带有两个下划线的标识符被保留用于实现(编译器,库,托管环境...),所以你不应该使用它们。)

答案 1 :(得分:0)

关于范围

来自3.1.2.1 ANSI C(类似于C99中的6.2.1):

  

如果是声明者或   声明标识符的类型说明符出现在块或   在函数定义的参数声明列表中,   标识符具有块范围,该范围终止于关闭的}   相关的块

...

  

如果外   声明词汇相同的标识符存在于同一个中   名称空间,它被隐藏,直到当前范围终止,之后   它再次变得可见。

因此,假设编译器是兼容的,您应该能够假设表达式中的变量范围不会影响外部范围中的变量