在 C 书中,它说:
至少内部名称的前 31 个字符是重要的。对于函数名和外部变量,数量可能小于 31,因为外部名称可能被语言无法控制的汇编程序和加载程序使用。对于外部名称,该标准仅保证 6 个字符和单个大小写的唯一性。if、else、int、float 等关键字是保留的:您不能将它们用作变量名。它们必须小写。
有人可以解释什么是“内部名称”、“外部名称”、“外部变量”吗?如果能举个例子就更好了。
我抚摸着我的白胡子,用圣洁而浮夸的声音说:
在过去,当 FORTRAN 和 COBOL 统治着计算世界时,新贵的语言 C 必须适应现有的工具链。这些工具链包括链接编辑器(a/k/a 链接器、a/k/a 加载器)和仅处理短 6 字符符号(变量和函数)名称的汇编器。
这些工具链的 C 编译器在写出供链接编辑器使用的目标文件时,不得不假装变量和函数名称很短。那是个坏消息。好消息是 C 程序中有很多符号不需要出现在目标文件中。
例如,函数的名称......例如“main”和“sqrt”......需要显示在目标模块中,因此来自其他目标模块的代码可以使用它们。“外部”样式全局变量的名称也是如此。这些是外部名称。
但是 C 程序中的所有其他名称,例如函数范围内的变量名称、结构成员的名称等等,都不必进入目标模块。这些被称为“内部名称”。
因此,例如,您可以在函数中包含这些 C 变量
int myFavoriteItem;
int myFavoriteThing;
那很好。但是您可以将它们声明为外部变量,如下所示:
extern int myFavoriteItem;
extern int myFavoriteThing;
一些系统会将这些名称写到目标文件中,就好像它们有六个字母一样长(因为目标文件不知道如何处理较长的名称)。然后他们会查看目标文件,就好像他们是这样声明的。
extern int myFavo;
extern int myFavo;
这些将是重复的声明。C 编译器需要捕获这种事情并抛出错误,而不是向目标文件写入重复的声明。这对程序员有很大帮助:目标文件中的重复声明会生成非常模糊的链接编辑器错误消息。
您引用的段落指定编译器必须识别至少 31 个内部名称字符和 6 个外部名称字符。现代编译器和工具链不再有不同的名称长度限制。
外部名称:
“外部”名称是对其他编译单元可见的名称,例如使用“extern”关键字声明的非静态函数和变量。这些名称必须暴露给链接器和加载器。在过去的日子里,一些链接器和加载器只能处理非常短的名称。
内部名称:
“内部”名称是在正在编译的模块之外不可见的名称——基本上是任何具有“静态”作用域的名称,或者是函数本地的任何名称。C 编译器必须处理这些名称,而不是其他任何东西
“内部名称”是函数内标识符的名称(实际上是局部变量名称)。
“外部名称”将是其他标识符的名称,包括函数名称和在全局范围内声明或使用存储类 extern 声明的任何标识符。
基本上,任何需要“外部可见”的东西都只能保证有 6 个(不区分大小写)唯一字符,这是非常有限的。
在实践中,这不再是一个问题。C99 增加了这些限制,大多数现代编译器取消或显着增加了这些限制。例如,Visual C++在编译 C 时允许所有标识符(内部或外部)中的唯一性为 247 个字符。
外部名称是具有外部链接的标识符。对于具有外部链接的标识符,它必须是文件范围的非静态或明确声明的“extern”。例子:
int global_variable;
int main(void)
{
int local_variable;
extern int extern_variable;
return 0;
}
在上面的示例中,标识符global_variable
和extern_variable
是外部名称。local_variable
是一个内部名称。
请注意,在实践中,重要字符的数量不仅仅是 31 和 6。例如,Microsoft 的 C 编译器默认使用 247 个重要字符作为内部和外部名称。GCC 将内部名称的所有字符视为重要字符。外部名称的重要字符取决于链接器(在大多数平台上,适用与内部名称相同的规则;所有字符都是重要的。)
ANSI 标准简单地规定了实现符合标准的有效字符的最小数量。