C语言中的“significant characters”在变量中扮演什么样的角色?

7

在C语言中,“significant characters”(显著字符)的确切作用是什么,特别是在变量领域?我已经阅读了主题“(K&R) At Least the first 31 characters...”,但我真的不理解显著字符的确切规则。唯一我能理解的是这个主题已经过时了,但我仍然需要知道!


2
你对那个问题的答案到底有什么不理解的地方? - Mat
4个回答

13
在当前的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个字符(将每个通用字符名称或扩展源字符视为单个字符)以下是一项过时的功能,这是对现有实现的让步。

这意味着在处理名称时,编译器必须将前63个字符内不同的内部名称视为不同,但如果你愚蠢到创建两个(或多个)仅在第64个字符中不同的标识符(前63个字符相同,但其中一个的第64个字符是,例如,1,而另一个是z),那么编译器可能会合法地且没有警告地将这两个标识符视为相同。
外部名称的限制 - 影响链接器而不是编译器本身的名称 - 可能仅限于31个字符。考虑:
extern int abcdefghijkjlmnopqrstuvwxyz123456;
extern int abcdefghijkjlmnopqrstuvwxyz123457;

如果系统(链接器)限制您只能使用31个字符,则这两个声明可以被视为引用同一变量。

正如未来方向部分所述,任何短于255的限制都是“过时的”,这意味着在名称达到255个字符之前,您不应受到此限制。但标准尚未规定255个字符作为限制。

历史

标准的先前版本对名称长度的上限有更小的下限。 C89标准仅强制要求外部名称为6个字符单大小写(但它被视为对现有链接器的痛苦让步),因此strcmpStrCmp可以相同,abcdefgabcdefz也可以相同。问题的一部分可能是Fortran; 它仅需要支持6个字符的单大小写名称,因此在广泛使用Fortran的系统上的链接器不需要支持更长的名称。

C99中的限制与C11相同。


那么我们可以推断:由于当今的集成开发环境中限制较少,它们的链接器可能不遵循精确的C99标准规则/基础? - kaymas
@kaymas:关于“IDE和C99”的问题——大多数现代链接器提供的限制都在或超出了C99所需的下限;理想情况下,它们不应该对名称的长度施加任何限制。这意味着它们符合C99标准(我引用的脚注18说,尽可能避免对名称长度施加限制)。一个链接器可能违反C99标准,不允许至少31个字符的名称,但我没有听说过这样的链接器。一个IDE应该知道标准以及它使用的编译器和链接器的任何限制。 - Jonathan Leffler
我想补充一下N2346/6.4.2.1p6的内容:如果两个标识符仅在不重要的字符上有所不同,则其行为是未定义的。正如你所指出的,编译器可能会合法地且没有警告地将这两个标识符视为相同,但无论如何都是未定义的行为。 - Some Name

2

在早期的C语言中,由于编译器和程序运行的计算机内存非常有限(考虑的是千字节而不是吉字节),为了节省内存,编译器仅使用标识符(变量名、函数名等)中的前八个字符(在早期编译器上)作为名称。这就是"有效字符"的作用,它是编译器在源代码中用于名称的字符数。


2
@kaymas 是的,绝对是这样。对于编译器来说,“foo_bar_123”和“foo_bar_135”这两个名称被视为相同的。 - Some programmer dude
1
我认为限制是由于链接器的限制,而不是编译器的限制。 - lhf
1
一些早期的(与Fortran兼容,基于大型机?)链接器对外部名称的单个大小写字符有6个字符的限制。C89标准只能强制规定外部名称为6个字符的单个大小写字符(因此A12345a12345是相同的)。到了C99,它们将要求增加到31个字符。大多数系统支持更多,因为C++名称重载通常需要长名称。 - Jonathan Leffler
1
@kaymas 哦,好的。大小写敏感一直是 C 语言的一部分,但一些早期的链接器并不关心名称的大小写,因此例如一个名为 FOO 的函数和一个名为 foo 的函数会导致重新定义错误。 - Some programmer dude
@JonathanLeffler | 谢谢。但是如果标识符中有多个字母会发生什么呢?例如,Ab1234和AB1234是否相同?那么现在的链接器呢? - kaymas
显示剩余4条评论

0

这里没有角色 - 重要字符的数量是C链接器所强加的限制。31个字符的限制是早期链接器使用的。


2
即使在ISO/IEC 9899:2011标准中,对于实现必须支持的有效字符数量也存在限制。 - Jonathan Leffler

0

以下是我的想法,

这意味着除了前31个字符以外的所有字符都将被忽略,即变量名:

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

将被视为:

ab..(27 characters)..yz

因此您可能会遇到重新声明错误...


好的,但是对于大小写字母的情况怎么办?想象一下这两个变量都有31个字符:ab..(27char)..yz和ab..(27char)..yZ;它们仍然是一个变量吗? - kaymas
@kaymas:有些编程语言是区分大小写的,而有些则不是,而且可以将大小写敏感和不敏感的组件链接在一起。有些系统要求非大小写敏感的语言必须仅以大写形式导出所有标识符(因此,如果函数Foo是用Pascal编写的,则C代码需要将其调用为FOO),但其他系统使用不区分大小写的链接。 - supercat
说“将被忽略”有点过于绝对了。使用“可能会被忽略”更为准确。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接