【问题标题】:What's the exact role of "significant characters" in C (variables)?C(变量)中“重要字符”的确切作用是什么?
【发布时间】:2013-08-19 20:30:49
【问题描述】:

“重要字符”在 C 中的确切作用是什么,尤其是在变量领域?我读过“(K&R) At Least the first 31 characters...”这个话题,但我真的不明白有效字符的确切规则。我唯一明白的就是这个科目已经绝迹了,但我还是要知道!

【问题讨论】:

  • 你对那个问题的答案有什么不完全理解的?

标签: c


【解决方案1】:

在当前的 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 个字符的大写字母(但这被认为是对现有链接器的痛苦让步),因此 strcmpStrCmp 可以相同,abcdefgabcdefz 也可以相同。部分问题可能出在 Fortran。它只需要支持 6 个字符的单大写名称,因此在广泛使用 Fortran 的系统上的链接器不需要支持更长的名称。

C99 中的限制与 C11 相同。

【讨论】:

  • 所以我们可以推断:由于当今 IDE 的限制较少,它们的链接器可能不遵循确切的 C99 标准规则/基础?
  • @kaymas: re 'IDEs and C99' - 大多数现代链接器提供的限制等于或超出 C99 要求的下限;理想情况下,它们不应对名称的长度施加任何限制。这意味着它们符合 C99 标准(我引用的脚注 18 说它们应尽可能避免对名称的长度施加限制)。链接器可能会违反 C99 标准,因为它不允许名称至少为 31 个字符,但我还没有听说过这样的链接器。 IDE 应该了解标准以及它使用的编译器和链接器的任何限制。
  • 我要补充一点 N2346/6.4.2.1p6 如果两个标识符仅在非重要字符上有所不同,则行为是未定义的。所以正如您所指出的,编译器可能是合法的,并且没有警告,将这两个标识符视为相同,但无论如何它都是 UB。
【解决方案2】:

在过去的 C 语言中,当编译器和程序在内存非常有限的机器上运行时(想想千字节,而不是千兆字节),为了节省内存,编译器最多只使用八个字符(在早期的编译器上)标识符(变量、函数等的名称)。这是“重要字符”的作用,它是编译器在源代码中用于名称的字符数。

【讨论】:

  • 好的,在 c 的早期,声明两个非常相似的变量,它们的差异仅限于“案例”,这是真的吗?
  • @kaymas 哦,是的,绝对是。从编译器的角度来看,foo_bar_123foo_bar_135 这两个名称将被视为相同。
  • 我认为限制是由于链接器中的限制,而不是编译器中的限制。
  • 一些早期的(与 Fortran 兼容的,基于大型机的?)链接器在外部名称上限制为 6 个字符。 C89 标准只能为外部名称规定 6 个字符的单大写字母(因此 A12345a12345 相同)。到 C99,他们将要求增加到 31 个字符。大多数系统支持更多,因为 C++ 名称修饰通常需要长名称。
  • @kaymas 好吧。区分大小写一直是 C 语言的一部分,但一些早期的链接器并不关心名称的大小写,例如一个名为 FOO 的函数和一个名为 foo 的函数会导致重新定义错误。
【解决方案3】:

这是我的想法,

表示忽略前31个字符之后的所有字符,即变量名:

ab..(27 characters)..yz123
ab..(27 characters)..yz578

将被视为:

ab..(27 characters)..yz

所以你会得到重新声明错误...

【讨论】:

  • 好的,但是案例呢?想象这两个变量都有 31 个字符: ab..(27char)..yz & ab..(27char)..yZ ;他们还是一个变量吗?
  • @kaymas:有些语言区分大小写,有些则不区分,并且可以将用区分大小写和不区分大小写的语言混合编写的组件链接在一起。有些系统要求不区分大小写的语言必须仅以大写形式导出所有标识符(因此,如果函数 Foo 是用 Pascal 编写的,C 代码将需要将其作为 FOO 调用),但其他系统使用不区分大小写的链接。
  • 说“将被忽略”太过分了。使用“可能被忽略”会更准确。
【解决方案4】:

没有任何作用 - 有效字符的数量是 C 链接器施加的限制。早期的链接器使用了 31 个字符的限制。

【讨论】:

  • 即使在 ISO/IEC 9899:2011 中,实现必须支持的重要字符的数量也存在限制。
猜你喜欢
  • 2010-10-19
  • 2010-09-10
  • 1970-01-01
  • 2018-05-13
  • 2014-12-11
  • 2021-12-23
  • 1970-01-01
相关资源
最近更新 更多