有趣的范围问题,解释?

Sam*_*Sam 1 c c++ objective-c

我刚刚发现了一个代码如下所示的错误:

char *foo = malloc(SOME_NUM * sizeof(char));
if (!processReturnsTrueOrFalse(foo)) {
    free(foo);
    char *foo = malloc(SOME_NUM * sizeof(char));
    // More stuff, whatever
}
Run Code Online (Sandbox Code Playgroud)

这可以编译,但我可以在同一个函数中定义两个变量,这很奇怪,但是编译器看起来有不同的范围.

如果是这种情况,我如何区分内部foo和外部foo?编译器是如何知道在我的第二次声明之前的免费中,我试图释放外部foo,但是当我重新声明内部foo时,它没有给我一个错误?

谢谢你的任何信息.这可能是一个非常明显的新手问题.

Ecl*_*pse 12

C++每次使用时都为变量定义了一个新的范围{ }.看看这个例子.

const char *foo = "global";

int main(int argc, char* argv[])
{
    const char *foo = "hello";

    {
        cout << foo << endl;
        const char *foo = "world";
        cout << foo << endl;
        cout << ::foo << endl;
    }
    cout << foo << endl;
}
Run Code Online (Sandbox Code Playgroud)

当你运行它时,你得到:

 hello
 world 
 global 
 hello

当您打开新作用域并声明与封闭作用域中的变量同名的变量时,只要保留在当前作用域中,就会将该变量隐藏在外部作用域中.离开内部范围后,外部变量将再次可见.如果外部变量恰好是globabl变量,则可以使用全局命名空间进行访问::foo.如果外部变量是类变量,则可以使用className::foo.如果外部变量只是一个局部变量,那么在您离开声明隐藏它的变量的范围之前,无法访问它.

我有一段时间没有使用过C,所以C99可能会有所不同,但在较旧的C中,无法访问隐藏的名称.

const char *foo = "global";

int main(int argc, char* argv[])
{
    const char *foo = "hello";

    {
        char *foo = "world";
        printf("%s\n", foo);
    }
    printf("%s\n", foo);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当你运行它时,你得到:

 world 
 hello

  • 没有C解决方案.在C中,您无法从封闭范围访问隐藏变量. (2认同)
  • @Josh:有C解决方案 - 请看我的帖子. (2认同)

qrd*_*rdl 5

正如其他海报写的那样,当在内部范围内声明具有相同名称的变量时,例如函数或块,就会影响变量.

但是有一种方法可以在C中访问带阴影的全局非静态变量:

int foo = 1;                       // global

int bar(void) {

    printf ("%d", foo);            // print global
    {
        int foo = 2;               // global foo shadowed
        printf ("%d", foo);        // print local
        {
             extern int foo;       // local foo shadowed
             printf("%d", foo);    // print global
        }                          // global foo shadowed
        printf ("%d", foo);        // print local
    }                              // end of scope for local foo
}
Run Code Online (Sandbox Code Playgroud)

我做了一些虚拟块,因为使用C99之前的编译器,你不能在块的中间声明变量.