我刚刚发现了一个代码如下所示的错误:
char *foo = malloc(SOME_NUM * sizeof(char));
if (!processReturnsTrueOrFalse(foo)) {
free(foo);
char *foo = malloc(SOME_NUM * sizeof(char));
// More stuff, whatever
}
这是编译,但我很可能在同一个函数中定义了两个变量,但是编译器看起来的范围不同。
如果是这种情况,我如何区分内部foo和外部foo?编译器是如何知道在我的第二次声明之前的免费中,我试图释放外部foo,但是当我重新声明内部foo时,它没有给我一个错误?
感谢您的任何信息。这可能是一个非常明显的新手问题。
答案 0 :(得分: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;
}
当你运行它时,你得到:
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;
}
当你运行它时,你得到:
world hello
答案 1 :(得分:5)
正如其他海报写的那样,当你在内部范围内声明具有相同名称的变量时,你shadow变量,例如功能或阻止。
但是有一种方法可以在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
}
我制作了一些虚拟块,因为使用C99之前的编译器,你无法在块的中间声明变量。
答案 2 :(得分:3)
你的第二个'foo'的范围从它的声明开始并一直持续到声明它的块的结尾。当你调用free(foo)时它会对第一个'foo'起作用,因为第二个foo没有已经宣布。
在声明第二个'foo'之后,无法访问外部'foo'。你基本上掩盖了这个名字。
答案 3 :(得分:3)
这不是错误,可以在不同的范围内声明具有相同名称的变量。
编译器知道free函数中的foo是外部函数,因为那时它是程序的唯一foo。
在宣布第二个foo之后你应该使用
::foo = ...
访问外部foo,(编辑)如果外部foo被声明为全局(在任何函数之外)。
答案 4 :(得分:2)
这是因为范围和符号表。
你在这里的例子比正常的范围更有线(我强烈建议不要使用这样的结构)。但解释是编译器在声明新变量时更新符号表,直到符号表查找落到外部范围。
正如您在此示例中所看到的,指针的地址会发生变化:
void *var = NULL;
{
std::cout << "From outer scope: " << &var << std::endl;
void *var = NULL;
std::cout << "From inner scope: " << &var << std::endl;
}