【发布时间】:2013-08-19 20:30:49
【问题描述】:
“重要字符”在 C 中的确切作用是什么,尤其是在变量领域?我读过“(K&R) At Least the first 31 characters...”这个话题,但我真的不明白有效字符的确切规则。我唯一明白的就是这个科目已经绝迹了,但我还是要知道!
【问题讨论】:
-
你对那个问题的答案有什么不完全理解的?
标签: c
“重要字符”在 C 中的确切作用是什么,尤其是在变量领域?我读过“(K&R) At Least the first 31 characters...”这个话题,但我真的不明白有效字符的确切规则。我唯一明白的就是这个科目已经绝迹了,但我还是要知道!
【问题讨论】:
标签: c
在当前的 C 标准中,ISO/IEC 9899:2011 第 §5.2.4.1 节 翻译限制 说:
实现应该能够翻译和执行至少一个程序 包含以下每一项限制的至少一个实例:18)
...
— 内部标识符或宏名称中的 63 个有效初始字符(每个 通用字符名称或扩展源字符被视为单个 字符)
— 外部标识符中的 31 个有效初始字符(每个通用字符名称 指定 0000FFFF 或更小的短标识符被视为 6 个字符,每个 指定 00010000 或更大的短标识符的通用字符名称是 考虑 10 个字符,并且每个扩展源字符都被认为是相同的 字符数作为对应的通用字符名称(如果有)19)
...18) 实施应尽可能避免施加固定的翻译限制。
19) 请参阅“未来语言方向”(6.11.3)。§6.11.3 外部名称
¶1 将外部名称的重要性限制为少于 255 个字符 (将每个通用字符名称或扩展源字符视为单个 character) 是一个过时的功能,是对现有实现的让步。
这意味着在处理名称时,编译器必须将前 63 个字符内不同的内部名称视为不同的,但如果您被误导到创建两个(或更多)在 64th 字符(前 63 个相同,但第 64th 个字符中的一个是 1,另一个是 z),然后是编译器可以合法地,在没有警告的情况下,将这两个标识符视为相同。
外部名称的限制——影响链接器而不是编译器本身的名称——可能被限制为少至 31 个字符。考虑:
extern int abcdefghijkjlmnopqrstuvwxyz123456;
extern int abcdefghijkjlmnopqrstuvwxyz123457;
如果系统(链接器)将您限制为 31 个字符,则这两个声明可能会被视为引用同一个变量。
正如未来方向部分所述,任何小于 255 的限制都是“过时的”,这意味着在名称长度为 255 个字符之前,您不应受此限制。但该标准还没有规定 255 个字符作为限制。
该标准的先前版本对名称长度上限的下限较小。 C89 标准只要求外部名称使用 6 个字符的大写字母(但这被认为是对现有链接器的痛苦让步),因此 strcmp 和 StrCmp 可以相同,abcdefg 和 abcdefz 也可以相同。部分问题可能出在 Fortran。它只需要支持 6 个字符的单大写名称,因此在广泛使用 Fortran 的系统上的链接器不需要支持更长的名称。
C99 中的限制与 C11 相同。
【讨论】:
N2346/6.4.2.1p6 如果两个标识符仅在非重要字符上有所不同,则行为是未定义的。所以正如您所指出的,编译器可能是合法的,并且没有警告,将这两个标识符视为相同,但无论如何它都是 UB。
在过去的 C 语言中,当编译器和程序在内存非常有限的机器上运行时(想想千字节,而不是千兆字节),为了节省内存,编译器最多只使用八个字符(在早期的编译器上)标识符(变量、函数等的名称)。这是“重要字符”的作用,它是编译器在源代码中用于名称的字符数。
【讨论】:
foo_bar_123 和 foo_bar_135 这两个名称将被视为相同。
A12345 和 a12345 相同)。到 C99,他们将要求增加到 31 个字符。大多数系统支持更多,因为 C++ 名称修饰通常需要长名称。
FOO 的函数和一个名为 foo 的函数会导致重新定义错误。
这是我的想法,
表示忽略前31个字符之后的所有字符,即变量名:
ab..(27 characters)..yz123ab..(27 characters)..yz578
将被视为:
ab..(27 characters)..yz
所以你会得到重新声明错误...
【讨论】:
没有任何作用 - 有效字符的数量是 C 链接器施加的限制。早期的链接器使用了 31 个字符的限制。
【讨论】: