为未签名的int分配负数不会导致任何错误?

时间:2019-07-19 13:25:54

标签: c int unsigned

为什么编译器不会为此生成错误

回答了一些问题,但并没有确切地找到原因。一些可以帮助我们提供一些简单的答案来了解这一点

#include <stdio.h>
int main()
{
    unsigned int a=-1;
    printf("Result :%d",a);
    return 0;
}

结果:-1

2 个答案:

答案 0 :(得分:2)

这是一个错误

    unsigned int a=-1;
    printf("Result :%d",a);

您不能使用"%d"打印无符号值,而必须使用"%u"

答案 1 :(得分:-2)

@Ganesh,

在这种情况下,编译器不会产生错误。

C语言为您提供了强大的功能,但您需要小心。使用“ unsigned”关键字告诉编译器如何处理MSB(最高有效位)。更准确地说,当您将类型“ int”的变量分配给内存位置时,它将在内存中保留一些空间(取决于平台)。为简单起见,假设int保留8位内存,因此:1 2 3 4 5 6 7 8.每个数字代表一个字节(8的序列)中的一个位(单个存储器位置,可以容纳0或1)。位)。当您声明:带符号整数并键入:

signed int a = -1;

编译器将执行以下操作:1 0 0 0 _ 0 0 0 1 1(_只是为了使一系列数字更易于阅读)。

这将不会被视为非常大的数字。这将被读为“负1”,因为最高有效位(从左到右读取的第一位)将被作为符号读取。这意味着带符号的int值仅使用7位(在此示例中)存储数字值,而将使用一位存储符号(0表示数字为正,1表示数字为负)。

“无符号”关键字有什么作用?

告诉编译器时:

unsigned int a = 1;

它完全改变了数字的读取方式。还记得那个记忆的地方:1 2 3 4 5 6 7 8吗?好吧,位置1的位将不再能够存储数字的符号。这意味着所有八位都将用于存储数字值。

在二进制情况下:1 0 0 0 _ 0 0 0 1作为有符号的int将被读取为-1,但作为无符号的值,它将是很大的值(您可以使用bin到dec转换器看到确切的数字在线,但这不是重点。

那么,您的代码有什么问题?第一个是:

(1) unsigned int a = -1;

第二个是:

(2) printf ("%d", a);

那么,让我们谈谈为什么第一条语句不会使代码崩溃?

C语言世界基于汇编程序指令(目前它们无关紧要),并且完全是二进制的。

C确实不在乎数字。它们只是在帮助程序员编写可读程序。

当您指定-1时,无论它是什么类型的数据,内存:1 2 3 4 5 6 7 8将被填充,如下所示:

1 2 3 4 .. 5 6 7 8
1 0 0 0 .. 0 0 0 1

故事的结尾。编译器按以下顺序操作:

(1)关键字(int,float,...):为变量保留空间 (2)值(-1):转换为二进制字 (3)故事结束。

当编译器转换文字(数字,例如:-1、60、2.63622,无论如何)时,它将始终在出现“-”符号的情况下将MSB分配为:1(再次:MSB为x 2 3 4 5 6 7 8,x位置)。在gcc上使用-Wall之类的编译器指令:

gcc -Wall test.c -o test.o

会给您所有警告:“我希望得到这个,但是我得到了”。警告可能是您最好的朋友,但我通常发现警告比受益者更为邪恶。

您甚至可以说:

int a = 5.125;

这是一个浮点数,但编译器不会争论(也许会发出警告,但不会出错)。

我认为这可以澄清原因:

unsigned int a = -1;

可以通过编译器。

第二件事是“ printf”。这可能是检查变量拥有什么值的最差方法,因为您会看到将-1分配给无符号变量,然后将其读出为-1。

这就是事实:1 0 0 0 _ 0 0 0 1对计算机没有任何意义。这只是一系列信息(电压的高/低值),但是计算机对于其他所有功能都是愚蠢的。程序使计算机能够理解这些信息的含义。

当您说:printf(“%d”,a),使用%d占位符时,您说的是:好的,请获取存储在变量“ a”中的信息。计算机得到:1 0 0 0 _ 0 0 0 1.正如我所知道的,计算机对其他所有东西都不了解。它无法理解这些电压系列(以数字表示)的含义。

那是%d进入的地方。它告诉计算机:好的,读取二进制值,其中第1位是符号值,然后将剩余的(7位)转换为十进制数,并在终端上打印出来(该黑框将显示已打印的数字,如果您使用Windows,则称为命令提示符)。

因此,%d是一个占位符,它告诉将使用符号的值解释获取的数字。这就是原因:

unsigned int a = -1;
>> -1

打印出-1。

但是,如果您要使用pmg所提到的%u空格,那么它将告诉编译器将:1 0 0 0 _ 0 0 0 1消息视为一个数字,其中没有任何位会代表数字的符号,因此,您将得到打印出类似6316136236136的信息(好的,不是很大,但您可能会明白这一点)。

总结起来,相当详尽,

(1)在C语言中,对变量类型要小心并保持一致; (2)请特别注意printf空格符,因为它们将以不同的方式解释该值,例如:

float a = 5.125;
printf("%f", a);
>> 5.1250
printf("%d", a);
>> god knows what number you'll get (I just got: 1508905080)

我希望这些信息能引导您走上正确的道路。您可以发表评论,我会尽快与您联系。