关于有符号数、无符号数和数据类型的总结

简介: 一、   CPU只会根据输入信号进行逻辑运算,在硬件级别是没有有符号无符号的概念,运算结束会根据运算前的信号和输出信号来设置一些标志位,是不是有符号由写程 序的人决定,标志位要看你把操作数当有符号还是无符号来选择,就像内存中的数据,你可以按照需要来解析,原始数据在那里,你要按什么数据格式来解析在于自 己的选择,所以玩汇编的要做到心里有数,加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。

一、

  CPU只会根据输入信号进行逻辑运算,在硬件级别是没有有符号无符号的概念,运算结束会根据运算前的信号和输出信号来设置一些标志位,是不是有符号由写程 序的人决定,标志位要看你把操作数当有符号还是无符号来选择,就像内存中的数据,你可以按照需要来解析,原始数据在那里,你要按什么数据格式来解析在于自 己的选择,所以玩汇编的要做到心里有数,加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:mul div movzx … 是处理无符号数的,而这些:imul idiv movsx … 是处理有符号的。举例来说:
内存里有 一个字节x 为:0x EC ,一个字节 y 为:0x 02 。当把x,y当作有符号数来看时,x = -20 ,y = +2 。当作无符号数看时,x = 236 ,y = 2 。下面进行加运算,用 add 指令,得到的结果为:0x EE ,那么这个 0x EE 当作有符号数就是:-18 ,无符号数就是 238 。所以,add 一个指令可以适用有符号和无符号两种情况。(呵呵,其实为什么要补码啊,就是为了这个呗,:-))
乘法运算就不行了,必须用两套指令,有符号的情况下用imul 得到的结果是:0x FF D8 就是 -40 。无符号的情况下用 mul ,得到:0x 01 D8 就是 472 。

二、

C又是可怕的,因为它把机器层面的所有的东西都反应了出来,像这个有没有符号的问题就是一例(java就不存在这个问题,因为它被设计成所有的整数都是有符号的)。为了说明c的可怕特举一例:
#include <stdio.h>
#include <string.h>

int main()
{
        int x = 2;
        char * str = "abcd";
        int y = (x - strlen(str) ) / 2;
       
        printf("%d\n",y);
}
结果应该是 -1 但是却得到:2147483647 。为什么?因为strlen的返回值,类型是size_t,也就是unsigned int ,与 int 混合计算时类型被自动转换了,结果自然出乎意料。。。
观察编译后的代码,除法指令为 div ,意味无符号除法,即将-2看做无符号数了。
解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认正好相反),这样一来,除法指令编译成 idiv 了。我们知道,就是同样状态的两个内存单位,用有符号处理指令 imul ,idiv 等得到的结果,与用无符号处理指令mul,div等得到的结果,是截然不同的!所以牵扯到有符号无符号计算的问题,特别是存在讨厌的自动转换时,要倍加小心!(这里自动转换时,无论gcc还是cl都不提示!!!)
为了避免这些错误,建议,凡是在运算的时候,确保你的变量都是 signed 的。

三、自动类型转化时的,短字节向长字节转化时,有符号数会符号扩展,无符号数会0扩展;长字节向短字节转化时,会自动截取高位,留下低位字节。特别在做算术运算时,比如乘除法,就可能涉及到有符号数自动转化为无符号数,从而采用不同的指令处理。

例如:下面的代码输出是什么,为什么?

void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
    这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ”>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式 计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

扩展一下,如果是这段代码呢?

 

void foo(void)
{
unsigned int a = 6;
int b = -20;
printf("%d\n",a+b);
(a+b > 6) ? puts("> 6") : puts("<= 6");
}

结果是输出:-14   >6   

 

为什么?我们要注意,在printf()中,a+b也是转换为unsigned int(0xF2)的,但是%d要求又是按照有符号数输出,所以0xf2当成有符号数输出了-14。

四。特别注意在有常数的算数表达式中,往往有隐含的数据类型转化,因为整数常量并没有明确的被指出其的数据类型,

整常数在不加特别说明时总是正值。如果需要的是负值,则负号“-”必须放置于常数表达式的前面。

每个常数依其值要给出一种类型。当整常数应用于一表达式时,或出现有负号时,常数类型自动执行相应的转换,十进制常数可等价于带符号的整型或长整型,这取决于所需的常数的尺寸。

八进制和十六进制常数可对应整型、无符号整型、长整型或无符号长整型,具体类型也取决于常数的大小。如果常数可用整型表示,则使用整型。如果常数值大于一 个整型所能表示的最大值,但又小于整型位数所能表示的最大数,则使用无符号整型。同理,如果一个常数比无符号整型所表示的值还大,则它为长整型。如果需 要,当然也可用无符号长整型。

但是,可以在一个常数后面加一个字母l或L强制其数据类型,则认为是长整型。如1 0 L、7 9 L、0 1 2 L、0 11 5 L、0 X A L、0 x 4 f L等。

L, U, LU,叫类型后缀,. 

 一般在程序中出现3种数据.我把它们叫,变量,常量,字面量.
变量,常量一般都已经规定了类型了的,所以后缀针对的是字面量.
由于语言默认,整数是int型.即字面量 12 是 int型的.
如果要表示 长整型的12 就得加后缀 12L,无符号的 12U,无符号长整型的12UL.
具体这些有什么用,你需要了解整数在内存中的存放形式...存放长度(位)...

 

相关文章
|
4月前
|
人工智能 自然语言处理 数据可视化
客户反馈闭环管理工具:从收集到解决的全程可视化方案
客户反馈是产品优化的重要依据,但常因渠道分散、信息杂乱、追踪困难等问题难以有效利用。客户反馈追踪可视化工具通过多平台聚合、信息结构化、全链路追踪及数据可视化,帮助团队高效管理反馈,提升问题响应速度与客户满意度,实现从“被动应对”到“主动优化”的转变。
|
C语言
C语言使用宏定义实现等级调试输出PRINT_LEVEL
C语言使用宏定义实现等级调试输出PRINT_LEVEL
424 0
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
312 58
|
存储 缓存 算法
带你理清CPU,cache和存储器之间的逻辑运作
带你理清CPU,cache和存储器之间的逻辑运作
3848 3
|
存储 缓存 安全
可重入函数与不可重入函数
可重入函数与不可重入函数
642 0
|
网络协议 Linux 网络安全
linux中跟踪路由命令,Linux命令:traceroute命令(路由跟踪)
【8月更文挑战第3天】traceroute是用来检测发出数据包的主机到目标主机之间所经过的网关数量的工具
686 5
|
机器学习/深度学习 人工智能 PyTorch
人工智能平台PAI 操作报错合集之机器学习PAI,用Triton Inference Server 22.05 部署模型,遇到SaveV3这个op的问题,如何解决
阿里云人工智能平台PAI (Platform for Artificial Intelligence) 是阿里云推出的一套全面、易用的机器学习和深度学习平台,旨在帮助企业、开发者和数据科学家快速构建、训练、部署和管理人工智能模型。在使用阿里云人工智能平台PAI进行操作时,可能会遇到各种类型的错误。以下列举了一些常见的报错情况及其可能的原因和解决方法。
|
存储
FreeRTOS入门教程(事件组概念和函数使用)
FreeRTOS入门教程(事件组概念和函数使用)
535 0
|
存储
CMOS门电路的介绍
CMOS门电路:高性能低功耗的数字电路设计方案 一、CMOS门电路的基本原理 CMOS(Complementary Metal-Oxide-Semiconductor)门电路是一种采用互补型金属氧化物半导体技术制造的数字电路。CMOS门电路由P型MOS(PMOS)和N型MOS(NMOS)两种互补型MOS管组成。PMOS管的导通与输入信号为低电平(0)相关,NMOS管的导通与输入信号为高电平(1)相关。通过组合不同的PMOS和NMOS管,可以实现与门、或门、非门、异或门等逻辑功能。 二、CMOS门电路的优势( CMOS门电路相比于其他门电路有许多优势。首先,CMOS门电
1038 0
|
编解码 网络协议 5G
【C/C++】uin8_t uint16_t uint32_t uint64_t数据类型解析
为了代码编写和阅读方便,我们通常会将数据类型名称声明为简写方式,即uin8_t/uint16_t/uint32_t/uint64_t,或者UINT8/UINT16/UINT32/UINT64。
2654 1
【C/C++】uin8_t uint16_t uint32_t uint64_t数据类型解析