整数常量不在可表示的范围内

时间:2017-03-06 23:05:56

标签: c constants language-lawyer

基于此(C11 6.4.4 / 2):

  

约束

     

2每个常数应具有一个类型,常数的值应为   在其类型的可表示值范围内。

写得正确:

unsigned long long int a=18446744073709551615;

因为整数常量(十进制常量)类型不能是unsigned。因此该值不在可表示的范围内。

exaclty会发生什么?该值不在十进制常量的可表示范围内。 ?

如果我是对的,如果相关联列表中没有可以表示常量的类型,则可以扩展整数常量。 这里的问题是十进制常量只能扩展为有符号整数常量。 所以数字18446744073709551615没有类型。

如何从无类型转换为unsigned long long int

2 个答案:

答案 0 :(得分:3)

根据最终得出某种结论的两条长评论线,我会对这个问题的答案产生危害:

  

写得正确:
  unsigned long long int a=18446744073709551615;

答案:也许;它依赖于实现。

在符合要求的实现中,long long int必须能够表示最小LLONG_MAX的数字,即+9223372036854775807(2 63 -1)(§5.2) .4.2.1)。由于有问题的数字比这大一些,因此不能保证它适合long long,因此无法保证它是可表示的。如果它不可表示,则程序违反约束(在第6.4.4.1节中),并且实现必须通过生成诊断消息来响应约束违规。

但是,给定的实现完全可以使long long int更宽泛。或者,它可以利用§6.2.5第4段(“可能还有实现定义的扩展有符号整数类型”)来定义另一种类型,比如int128_t,它比long long int宽。 。因此,数字可以在一致的实现中表示,并且使用具有这种实现的程序是完全有效的,如§4第7段所示,其表明符合的程序“是符合实现可接受的程序”。因此,程序员可以利用他们对正在使用的实现可接受的知识,如果整数常量对于他们的实现是可接受的,那么就不需要诊断。

§4还定义了一个更强大的程序类别,严格符合程序(第5段),它应该在所有符合要求的实现之间移植。上述整数常量并不严格一致,因此程序的有效性取决于实现。

实际上,clang和gcc都接受该程序,但不是因为它们有更宽的整数。产生的诊断是:

  

警告:整数文字太大而无法用有符号整数类型表示,解释为无符号         [-Wimplicitly-无符号字面]

足以符合标准,并指明了他们即将采取的行为。生成所需的诊断后,C标准不再适用。程序员已经收到警告,如果实现仍然生成可执行文件,则需要记录该可执行文件的功能。在此问题中,约束违规之间没有区别,或者语法错误:如果符合标准的编译器希望接受C标准中未定义的语法(可能期望它将成为未来标准的一部分),则它是只要它产生所需的诊断,就可以自由地这样做。如果编译器自动检测Java,C ++或Python,并选择生成“适当的”可执行文件,那么该文件不在C标准之内,因为该程序不是C程序并且已通知程序员那个事实。

对于较大的整数,clang和gcc生成的消息是

  

错误:整数文字太大而无法在任何整数类型中表示

并且没有生成可执行文件。这也符合标准,争议较少。

答案 1 :(得分:2)

在这种情况下,违反了约束 1

每个常量必须具有 2 类型。

在您的示例中,常量18446744073709551615无法在int,long int或long long int中表示,对于没有后缀的十进制常量,指定 3 。在这种情况下,常量不具有类型 4 ,违反了上面提到的 2 约束。

如果违反约束,编译器必须产生警告或错误消息 5

虽然这在技术上并不是未定义的行为,但是不应该允许编译器继续编译并生成可执行文件。大多数编译器都会停止编译这样的代码。

(引自:ISO / IEC 9899:201x)

1 (3。术语,定义和符号3.8约束1)
 限制,无论是句法还是语义,通过它来阐释语言元素 待解释

2 (6.4.4常数2)
每个常量都应具有类型

3 (6.4.4.1整数常数5)
整数常量的类型是其值可以在其中的第一个相应列表 代表。

4 (6.4.4.1整数常数6)
如果整数常量不能用任何类型表示 它的列表并没有扩展的整数类型,那么整数常量没有类型。

5 (5.1.1.3诊断1)
符合要求的实施应产生至少一条诊断信息(在 如果是预处理翻译单元或翻译单元,则是实现定义的方式 包含违反任何语法规则或约束的行为,即使行为也是明确的 指定为未定义或实现定义。

相关问题