C数据类型的范围

时间:2018-06-20 10:41:12

标签: c types

#include <math.h>

int main(){

    signed char b = 32767;
    if (b){
        printf("YES");
    }
    else
        printf("NO");
}

我没想到它会编译,因为带符号的char的范围是[−127,+127]?我还尝试输入一个8位的值(12345678),该值也可以编译为9位,但是导致我的Avast防病毒程序挂起,我以为程序已挂起,但过一会儿就编译了。我的问题是不应该对于有符号的char数据类型,编译器会拒绝[−127,+127]以外的任何值吗?

2 个答案:

答案 0 :(得分:0)

C是一种古老的语言。不要说“我没想到会因为...而编译”之类的话。通常,大多数C编译器会尽力为您编译某物,即使这样做很危险。不要说“编译器不会拒绝超出范围的任何值吗?”之类的事情。大多数C编译器不会仅仅因为它们是一个坏主意,甚至因为它们可能不起作用而拒绝事物。

大多数现代编译器都会警告您有关错误的主意,但是即使那样,您可能仍必须明确请求此类警告,因为在默认模式下,编译器可能仍会在老派的假设,即程序员知道他在做什么。

在C语言中,unsigned类型的溢出保证了行为-实际上,总是执行算术运算,实际上是对类型的大小取模。尽管不能保证,但是大多数处理器和大多数编译器也对签名类型实现相同的溢出处理,并且可能有相当数量的代码依赖于此。因此,这是编译器关于有符号整数溢出的警告不一定突出的另一个原因。

尽管如此,我还是在两个不同的编译器下尝试了您的代码。一个说“警告:隐式常量转换中的溢出”,另一个说“警告:从'int'到'signed char'的隐式转换将值从32767更改为-1”。

如果编译器未向您发出此类警告,则您将需要(a)确保所有警告均已启用(通过某处“配置设置”对话框中的复选框,或使用诸如{ {1}}),或(b)获得更好的编译器。

答案 1 :(得分:0)

使用C语言,您可以尝试将较大的类型显示为较小的类型,尽管这样做的方式定义不明确,也不应该依赖。

在此行initialValue上,您尝试将setState存储在signed char b = 32767;内。然后适用的是C标准(C11 6.3.1.3/3)中的该部分:

  

否则,将对新类型进行签名,并且无法在其中表示值;要么   结果是实现定义的或引发实现定义的信号。

因此,将要发生的事情没有明确定义,而是留给系统和编译器处理。在典型的2补码系统中,很可能采用int的二进制值,将除LS字节= {signed char以外的所有内容都切掉,然后将其转换为32767 = 0x7FFF数字,表示十进制{ {1}}。

话虽这么说,您的代码实际上没有任何意义,并且在实际应用程序中也没有使用此类代码,因此好的编译器会为此警告您。


弹出反病毒的原因是反病毒讨厌程序员。它发现您尝试更改可执行文件(您自己程序的二进制输出)。我建议在用于编程的计算机上禁用/卸载防病毒软件。