来自 C99 标准:
6.2.1/2
对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本区域内可见(即,可以使用)。由同一标识符指定的不同实体要么具有不同的范围,要么位于不同的名称空间中。
我对实体和标识符(我知道它可以是对象的名称)感到困惑。根据此引用示例,实体到底是什么?
实体是变量、函数、类型等。标识符是这些实体的名称。例如:
#include <stdlib.h>
#include <stdio.h>
static int foo()
{
static int x = 0; // "x" is an identifier, the variable "x" inside
// this function "foo()" is an entity.
return x++;
}
int main()
{
int x = 1; // "x" is an identifier as well, and it is the same name "x"
// as of that used inside "foo()". However, this entity
// (variable) is not the same as in "foo()", it has different
// scope and is a totally different entity.
printf("foo()+x++ = %d\n", foo()+x++);
printf("foo()+x++ = %d\n", foo()+x++);
printf("foo()+x++ = %d\n", foo()+x++);
return EXIT_SUCCESS;
}
请注意,单个标识符可以同时指定不同的实体。
#include <stdio.h>
static int x = 42; // 1
struct x { int x; }; // 2 & 3
int func(struct x x) // 4
{
if (x.x > 10) goto x; // 5
int y = x.x;
{
int x = 37; // 6
printf("%d %d\n", x, y);
}
x: // 7
return(x.x);
}
我认为我们可以同意x
这是一个彻底过度使用的标识符。
x
int
是文件范围内的静态类型变量。x
是一个结构标签。x
是结构成员。x
是类型的参数/局部变量struct x
(隐藏文件范围变量)。x
是对标签的引用。x
是一个新的局部变量(隐藏文件范围变量和参数)。x
是标签的定义。对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本区域内可见(即,可以使用)。由同一标识符指定的不同实体要么具有不同的范围,要么位于不同的名称空间中。
结构标记x
从第一次引用到文件末尾的位置可见。它位于标签命名空间中,因此不会与x
. 标签x
位于标签名称空间中,因此它不会与x
. 该结构成员x
位于“成员的struct x
”命名空间中,并且与x
. 这些是三个特殊的名称空间。
其他引用x
都在“普通标识符”命名空间中。Typedef 名称也在普通命名空间中;这就是为什么我没有使用typedef
. 调用的三个不同变量x
具有不同的作用域。
我已经放弃了宏命名空间;如果我#define x z
在开始时添加,那么我所说的一切x
都必须是关于“z
预处理后”的。
实体是变量,我的意思是它暗示了一些包含数据的内存(或寄存器),或编译对象,如类型、枚举等,它们具有一些属性,如大小、组件字段等。标识符只是某些实体的名称.
两个可区分的实体可以具有相同的名称(取决于范围),但在程序的任何一点上,一个名称只匹配一个实体。
考虑以下 C 程序
#include<stdio.h>
int main(void)
{
int var1, var2;
.....
.....
}
int newfun(void)
{
int var1;
float var2;
....
....
}
因此,对于每个不同的实体(可以被认为是一个变量),一个标识符(变量名,上图:var1,var2)可以在程序文本的区域内使用。即,main() 函数中定义的 var1 和 var2 只能在其中使用。
虽然 main() 和 newfun() 函数中的标识符是相同的,即 int var1 和 float var2。它们在每个函数中的处理方式不同。
现在,main() 函数中的变量(或标识符)是 int 类型。它们可以统称为一个实体。但是,下一个函数中的同一个变量 var2 是 float 类型,它属于不同的类型,因此属于不同的实体。