c中变量声明的模糊行为

时间:2014-11-02 11:49:55

标签: c variables variable-declaration

我有以下代码

#include<stdio.h>
int main()
{
    int a12345678901234567890123456789012345;
    int a123456789012345678901234567890123456;
    int sum;

    scanf("%d",&a12345678901234567890123456789012345);
    scanf("%d",&a123456789012345678901234567890123456);
    sum = a12345678901234567890123456789012345 + a123456789012345678901234567890123456;
    printf("%d\n",sum);

    return 0;
}

问题是,我们知道ANSI标准识别最多31个字符的变量......但是,两个变量最多相同,最多35个字符......但是,程序编译时仍然没有任何错误和警告并给出正确的输出......
但是怎么样? 它不应该给出重新声明的错误吗?

5 个答案:

答案 0 :(得分:15)

许多编译器的构建超出ANSI规范(例如,识别超过31个字符的变量名称)作为程序员的保护。虽然它适用于您正在使用的编译器,但您不能指望它只适用于任何C编译器......

答案 1 :(得分:10)

  

[...]我们知道ANSI标准识别最多31个字符的变量[...]不应该给出重新声明的错误吗?

嗯,没必要。由于您提到了ANSI C,这是C89标准的相关部分:

  

&#34;实施限制&#34;

     

实现应将内部名称的至少前31个字符(宏名称或没有外部链接的标识符)视为重要内容。相应的小写和大写字母是不同的。实现可以进一步限制外部名称(具有外部链接的标识符)对六个字符的重要性,并且可以忽略对这些名称的字母大小写的区别。 10 这些对标识符的限制都是实现定义

     

任何重要字符不同的标识符都是不同的标识符。 如果两个标识符在非重要字符中不同,则行为未定义

http://port70.net/~nsz/c/c89/c89-draft.html#3.1.2(强调我的)

它也明确地描述为公共扩展名

  

标识符的长度和个案

     

标识符中的所有字符(有或没有外部链接)都很重要,并且会观察到区别(3.1.2)

http://port70.net/~nsz/c/c89/c89-draft.html#A.6.5.3

因此,您只是在利用编译器的C实现选择。

答案 2 :(得分:3)

C89 rationale详细说明了这一点:

  

3.1.2标识符

     

虽然实现没有义务记住比第一个更多   用于名称匹配的标识符的31个字符,   有效地禁止程序员有意创建两个   前31个字符中相同的不同标识符。   因此,实现可以存储完整标识符;他们不是   被迫截断为31.

     

决定将内容的重要性扩展到31个字符   这些名字几乎没有反对,但决定保留   旧的六字符不区分大小写的意义限制   外部名字最痛苦。虽然表达了强烈的情绪   通过在任何地方要求更长的名字来使C“正确”   委员会认识到,语言必须在未来几年内,   与其他语言共存,与旧的汇编程序和链接器共存。   而不是破坏对标准的支持,严重   限制已被保留。

GCC之类的编译器可能会存储完整的标识符。

  
      
  • 标识符中的重要初始字符数(C90 6.1.2,C90,C99和C11 5.2.4.1,C99和C11 6.4.2)。

         

    对于内部名称,所有字符都很重要。对于外部   名称,重要字符的数量由链接器定义;   对于几乎所有目标,所有角色都很重要。

  •   

答案 3 :(得分:3)

符合标准的实现必须支持至少 31个字符作为外部标识符(并且您的标识符是内部的,C99和C11的限制为63)。

事实上,让所有字符都很重要是标准的意图,但是委托人不希望通过不提供它来使实现不符合。外部标识符的限制源于某些链接器无法提供更多(在C89中,只需要6个字符是重要的,这就是旧标准库函数的名称不超过6个字符的原因)。

准确地说,标准并没有完全规定这些限制,标准中的语言非常宽松:

C11(n1570)5.2.4.1 翻译限制

  

实现应能够翻译和执行至少一个包含以下每个限制的至少一个实例的程序: 18)

     
      
  • [...]
  •   
  • 内部标识符或宏名称中的63个重要初始字符(每个通用字符名称或扩展源字符被视为单个字符)
  •   
  • 外部标识符中的31个重要的初始字符(指定短标识符0000FFFF或更少的每个通用字符名称被认为是6个字符,每个指定短标识符00010000或更多的通用字符名称被认为是10个字符,并且每个扩展源字符被认为是与相应的通用字符名称相同的字符数,如果有的话) 19)
  •   
  • [...]
  •   

脚注18)清楚地表达了意图:

  

实施应尽可能避免强加固定的翻译限制。

脚注19)指的是未来语言方向 6.11.3:

  

将外部名称的重要性限制为少于255个字符(将每个通用字符名称或扩展源字符视为单个字符)是一个过时的功能,它是对现有实现的让步。

并解释5.2.4.1第一句中的宽容,参见C99基本原理(5.10)

  

5.2.4 环境限制

     

C89委员会同意标准必须说明某些能力和限制,但是如何执行这些条约要点是一个备受争议的话题。

     

5.2.4.1 翻译限制

     

标准要求实施能够翻译和执行满足每个规定限制的某些程序。人们认为这一标准为实施者在满足这些限制方面提供了有用的自由。虽然缺乏实施可能会设计出满足这一要求的计划,但仍然没有成功,C89委员会认为,这样的聪明才智可能需要更多的工作而不是创造有用的东西。 C89和C99委员会的意义在于,实施者不应将翻译限制解释为硬连线参数的值,而应将其作为判断实施的一套标准。

答案 4 :(得分:2)

没有限制。 实际上有一个限制,它必须足够小,以适应内存,但否则没有。如果有一个内置限制(我不相信有)它是如此巨大,你将真的很难达到它。一世 生成带有2个变量的C ++代码,这些变量具有不同的最后一个字符,以确保长不同的名称。我得到64KB文件并认为这已经足够了。