unsigned_unsigned char - CSDN
精华内容
参与话题
  • unsigned 关键字,你真的懂了吗?

    万次阅读 多人点赞 2013-07-11 11:29:02
    前不久和同事谈论起 unsigned 关键字,故今天小结一下。 以32位机为例,int 分为无符号 unsigned 和有符号 signed 两种类型,默认为signed。二者的区别就是无符号类型能保存2倍于有符号类型的数据。32位下,signed ...

    前不久和同事谈论起 unsigned 关键字,故今天小结一下。

    以32位机为例,int 分为无符号 unsigned 和有符号 signed 两种类型,默认为signed。二者的区别就是无符号类型能保存2倍于有符号类型的数据。32位下,signed int 的表示范围为:-2147483648 ~ 2147483647 (最高位做符号位)。unsigned int 的表示范围为:0 ~ 4294967295 (不保留符号位)。我们都知道,两个不同的数据类型在进行混合使用时,会自动进行类型转换。其转换原则就是:向着精度更高、长度更长的方向转换。也就是我们平常见到的 char 转为 int ,int 转为 long,float 转为 double  . etc. 那么当涉及到unsigned 类型时,又会进行怎样转换呢?下面来看个小例子:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int arr[]={1,2,3,4};
        if(-1<sizeof(arr)/sizeof(arr[0]))
            printf("Hello world!\n");
        else
            printf("Error!\n");
        return 0;
    }

    按照我们平时的逻辑:sizeof(arr)=4 (数组长度), sizeof(arr[0]) =4 (int 所占字节),所以,if(-1<1) 成立,执行hello world。可事实却相反,输出为Error。

    下面我们看一下它的反汇编:(不想看的童鞋可以跳过)

    int main()
    {
    00F31690  push        ebp  
    00F31691  mov         ebp,esp  
    00F31693  sub         esp,0DCh  
    00F31699  push        ebx  
    00F3169A  push        esi  
    00F3169B  push        edi  
    00F3169C  lea         edi,[ebp-0DCh]  
    00F316A2  mov         ecx,37h  
    00F316A7  mov         eax,0CCCCCCCCh  
    00F316AC  rep stos    dword ptr es:[edi]  
    00F316AE  mov         eax,dword ptr [___security_cookie (0F37000h)]  
    00F316B3  xor         eax,ebp  
    00F316B5  mov         dword ptr [ebp-4],eax  
        int arr[]={1,2,3,4};
    00F316B8  mov         dword ptr [ebp-18h],1  
    00F316BF  mov         dword ptr [ebp-14h],2  
    00F316C6  mov         dword ptr [ebp-10h],3  
    00F316CD  mov         dword ptr [ebp-0Ch],4  
        if(-1<sizeof(arr)/sizeof(arr[0]))
    00F316D4  xor         eax,eax  
    00F316D6  je          main+61h (0F316F1h)  
            printf("Hello world!\n");
    00F316D8  mov         esi,esp  
    00F316DA  push        offset string "Hello world!\n" (0F3577Ch)  
    00F316DF  call        dword ptr [__imp__printf (0F382CCh)]  
    00F316E5  add         esp,4  
    00F316E8  cmp         esi,esp  
    00F316EA  call        @ILT+320(__RTC_CheckEsp) (0F31145h)  
        else
    00F316EF  jmp         main+78h (0F31708h)  
            printf("error\n");
    00F316F1  mov         esi,esp  
    00F316F3  push        offset string "error\n" (0F35774h)  
    00F316F8  call        dword ptr [__imp__printf (0F382CCh)]  
    00F316FE  add         esp,4  
    00F31701  cmp         esi,esp  
    00F31703  call        @ILT+320(__RTC_CheckEsp) (0F31145h)  
        return 0;
    00F31708  xor         eax,eax  
    }

    注意一下第22,23行,xor     eax,eax  异或运算的结果为0,所以总会跳转至0F316F1h。执行Error语句。

    下面我们再修改一下这个程序:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int arr[]={1,2,3,4};
        if((double)-1<sizeof(arr)/sizeof(arr[0]))
            printf("Hello world!\n");
        else
            printf("error\n");
        return 0;
    }
    注意,这次我们在if语句里,将-1转换成了double类型。编译运行一下:hello world 。我们想要的结果终于出来了,在我们欣喜的同时,不禁要问:why ? 

    我们再来看一下它的汇编:

    int main()
    {
    00BE1690  push        ebp  
    00BE1691  mov         ebp,esp  
    00BE1693  sub         esp,0DCh  
    00BE1699  push        ebx  
    00BE169A  push        esi  
    00BE169B  push        edi  
    00BE169C  lea         edi,[ebp-0DCh]  
    00BE16A2  mov         ecx,37h  
    00BE16A7  mov         eax,0CCCCCCCCh  
    00BE16AC  rep stos    dword ptr es:[edi]  
    00BE16AE  mov         eax,dword ptr [___security_cookie (0BE7000h)]  
    00BE16B3  xor         eax,ebp  
    00BE16B5  mov         dword ptr [ebp-4],eax  
        int arr[]={1,2,3,4};
    00BE16B8  mov         dword ptr [ebp-18h],1  
    00BE16BF  mov         dword ptr [ebp-14h],2  
    00BE16C6  mov         dword ptr [ebp-10h],3  
    00BE16CD  mov         dword ptr [ebp-0Ch],4  
        if((double)-1<sizeof(arr)/sizeof(arr[0]))
    00BE16D4  mov         eax,1  
    00BE16D9  test        eax,eax  
    00BE16DB  je          main+66h (0BE16F6h)  
            printf("Hello world!\n");
    00BE16DD  mov         esi,esp  
    00BE16DF  push        offset string "Hello world!\n" (0BE577Ch)  
    00BE16E4  call        dword ptr [__imp__printf (0BE82CCh)]  
    00BE16EA  add         esp,4  
    00BE16ED  cmp         esi,esp  
    00BE16EF  call        @ILT+320(__RTC_CheckEsp) (0BE1145h)  
        else
    00BE16F4  jmp         main+7Dh (0BE170Dh)  
            printf("error\n");
    00BE16F6  mov         esi,esp  
    00BE16F8  push        offset string "error\n" (0BE5774h)  
    00BE16FD  call        dword ptr [__imp__printf (0BE82CCh)]  
    00BE1703  add         esp,4  
    00BE1706  cmp         esi,esp  
    00BE1708  call        @ILT+320(__RTC_CheckEsp) (0BE1145h)  
        return 0;
    00BE170D  xor         eax,eax  
    }
    注意第22,23,24行,test  eax, eax  与运算的结果为1,je不跳转,就继续执行了hello world。

    如此看来,是编译器在编译源代码的时候,做了一些我们不知道的工作。查一下文档,找到这么一段:

    ANSI C 标准采用值保留(value preserving)原则,就是当把几个整型操作数混合使用时,其结果的类型可能是有符号数,也可能是无符号数,这取决于操作数的类型的相对大小。(通俗点说,就是两个整型数,如果都转换为signed不会丢失信息,就转换为signed;否则就转换为unsigned。)

    在例一中,if(-1<sizeof(arr)/sizeof(arr[0])) 由于signed int 和unsigned int 都转换为 signed 时,unsigned 会丢失信息(unsigned正数表示范围是signed的2倍,当然会丢失信息了)。故根据ANSI C 标准,两者都转换为 unsigned 类型。而-1 转为无符号类型为:4294967296 。是的,你没看错,-1 在计算机内以补码形式存放,转换成十进制后,就变成了这个巨大的正数:4294967296。所以,if(4294967296<1) 永远为假,一直输出Error了。

    在例二中,我们将-1先转换成了8个字节的double类型。然后再和4个字节的unsigned类型比较时,由于double完全容得下unsigned。所以,此时,操作数都转换为有符号的double类型。所以 if( (double)-1 < (double)1) 成立。此时,就输出 hello world了。

    总结:尽量不要在你的代码中使用无符号类型,以免增加不必要的复杂性;或者使用时,在涉及混合运算时,进行强制类型转换,这样就不必由编译器来选择转换类型了。

    ------------------------------------------------------------------------------------------------------

    补充一点:

    1,ANSI C 标准中采用的是值保留原则。而K&R C 标准中,采用的是无符号保留(unsigned preserving)原则,即:不区分操作数大小,统一转换为无符号类型。如果采用K&R C 标准的话,那么例一、例二就都会输出Error了。

    2,当前编译器基本都遵循ANSI C 标准。如:gcc默认GNU C。

    即:GNU C = C90 + GNU Extensions = C90 + (some features in C99 + some features in C11)

    展开全文
  • unsigned与signed区别

    千次阅读 2018-05-06 18:56:40
    1.关于unsigned与signed区别:这两个适用于判定数值前面是否有符号,unsigned表示无符号,signed表示有符号。
    1.关于unsigned与signed区别:这两个适用于判定数值前面是否有符号,unsigned表示无符号,signed表示有符号。
    展开全文
  • UNSIGNED关键字的解释和用法

    千次阅读 2020-07-07 17:22:31
    UNSIGNED关键字 UNSIGNED表示无符号数,当定义一个数值型字段中添加该约束,表示该字段的数据没有符号,可以变相增加长度 举个例子,比如 tinyInt ,微整型数据类型,占一个字节,也就是 28 ,-127~128 是他的取值...

    UNSIGNED关键字

    UNSIGNED表示无符号数,当定义一个数值型字段中添加该约束,表示该字段的数据没有符号,可以变相增加长度

    举个例子,比如 tinyInt ,微整型数据类型,占一个字节,也就是 28 ,-128~127 是他的取值范围,但是添加 UNSIGNED 之后,他就是真正实现了 28,即 256,这个时候就没有负数了,当为主键 id 设为UNSIGNED后可以充分使用他的空间,因为默认重 0 开始,而-128~0 (假设数据类型为 tinyInt )这块空间,一般情况是用不到的,可以把这一块空间挪到后面去,变成1~256,这就是UNSIGNED的作用,因为并没有真正改变字段数据类型的长度,只是把它用不上的空间挪到了可用空间,所以我称它为变相增加长度。

    展开全文
  • C/C++ unsigned 详细探讨

    万次阅读 2018-07-24 11:59:02
    unsigned常应用于无符号数的表示,初学者可能并不知道其在具体应用中的潜在威胁,本文通过一些实例来具体说明。 unsigned char text_digit = -11; unsigned修饰无符号数,-11的补码是11的原码(0000 1011)取反...

      unsigned常应用于无符号数的表示,初学者可能并不知道其在具体应用中的潜在威胁,本文通过一些实例来具体说明。

    unsigned char text_digit = -11;

    unsigned修饰无符号数,-11的补码是11的原码(0000 1011)取反加一:1111 0101(十进制为245) 

    再此特别注意在if()语句中使用无符号数,若当成负数来看往往会造成很严重的后果

     

     

     

     

    还得注意 unsigned 修饰不同的类型所代表的的大小都不一样。

    样例改为 int

    总结:unsigned int a和 int b加法运算注意溢出,做减法运算所得到的值自动转换为unsigned类型,c语言中不同精度的值的运算,所得结果往高精度的方向转换而unsigned的精度高于有符号,while(a -b) 这个是死循环,永远为真,因为 不管a>b还是a<b,最后结果都是无符号数。无符号数永远大于0.

     

    展开全文
  • unsigned

    千次阅读 2018-04-15 16:22:11
    int分为unsigned(无正负号)和signed(有正负号)一般int默认为signedunsignedunsigned int意思相同
  • unsigned a:1;

    千次阅读 2017-02-22 17:30:36
    位域  有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据...
  • mysql中的unsigned是什么意思???

    万次阅读 2019-10-06 00:09:29
    unsigned 为“无符号”的意思, unsigned,zerofill 既为非负数,用此类型可以增加数据长度, 例如如果 int最大是65535,那 int unsigned zerofill 最大 就是 65535 * 2 ===============================...
  • 【MySQL】 unsigned使用

    千次阅读 2019-08-05 11:23:39
    `id` int unsigned not null auto_increment, primary key (`id`) ); 案例分析 针对上边的表插如一条数据 insert into yyy values(255); 这时我们在插入一条数据,这个时候会报出一个错,可以看到这个值是插入...
  • mysql中的unsigned是什么意思

    千次阅读 2018-12-18 15:13:29
    转... unsigned 为“无符号”的意思,     unsigned,zerofill 既为非负数,用此类型可以增加数据长度,   例如如果 int最大是65535,那 int unsigned z...
  • c++ unsigned char *与string 的相互转换

    万次阅读 2019-01-21 16:37:33
    **string 转unsigned char *** string pcbasn=“ABC1234567890” unsigned char *data = (unsigned char *)pcbasn.c_str(); **unsigned char * 转 string ** unsigned char tt[128] = { 0 }; string result= static_...
  • string与unsigned char*的相互转化

    万次阅读 2015-06-18 15:02:23
    1,string到unsigned char*  先将string转化为unsigned char *    2,unsigned char*转化为string  先将unsigned char*转化为char *
  • 用C语言实现循环左移,右移

    万次阅读 2010-11-29 11:35:00
      C51中实现循环左移、右移的库函数: #include unsigned char _crol_( unsigned char c, /*...unsigned char _cror_(unsigned char ,unsigned char ); unsigned int _iror_(unsigned int
  • 1、unsigned的作用就是将数字类型无符号化, 例如 int 型的范围:-2^31 ~2^31 - 1,而unsigned int的范围:0 ~ 2^32。看起来unsigned 是个不错的类型,尤其是用在自增或者没有负数的情况。但是在实际使用中会出现...
  • c++ string转化为const unsigned char*

    万次阅读 2016-12-20 16:06:07
    string-->const unsigned char*:  (const unsigned char*)string.c_str()  或者 const unsigned char* s =static_cast (string.c_str()) const unsigned char*-->unsigned char*:  ...
  • C语言中unsigned long long数据类型

    万次阅读 2017-04-21 11:53:55
    unsigned long long类型是目前C语言中精度最高的数据类型,可以用来表示20以内的阶乘数据,20以外的自测。 还有是unsigned long long的精度64位,double或者long double 虽然也占有8个字节,但是他们的实际精度...
  • unsigned long long ,long long ,int 等其他的数据的范围:
  • 参考博客:C语言 unsigned 和 signed 类型相互转换深入理解 参考博客:unsigned和signed 对于unsigned 无符号数据类型是不应该向其赋值负数的,但是如果赋值了那会怎么样呢? #include #include int main() { ...
  • PIC18F45K80 CAN通讯示例代码

    千次阅读 2016-02-17 09:30:43
    这里转载的是别人现成的代码,进行了实际的编译和下载运行,罗列了实际运行中出现的问题,主要是证明代码的可靠性。 1、新建工程、选择好器件、选择编译环境,我当时选择的是C:\Program Files (x86)\Microchip\...
  • 求这两个类型的相互转换的代码,同时还想问下怎样将大文件转换为 unsigned char [] 类型。(验证文件时过大读不进内存)
  • 碰到格式转换就收藏下来!
1 2 3 4 5 ... 20
收藏数 682,068
精华内容 272,827
关键字:

unsigned