有符号数和无符号数之间的转换(2020)C

有符号数和无符号数之间的转换

C语言允许在各种不同的数字数据类型之间做强制类型转换。例如,假设变量x声明为int,u声明为unsigned。表达式(unsigned)x会将x的值转换成一个无符号数值,而(int)u将u的值转换成一个有符号整数。将有符号数强制类型转换成无符号数,或者反过来,会得到什么结果?从数学的角度来说,可以想象到几种不同的规则。很明显,对于在两种形式中都能表示的值,我们是想要保持不变的。另外一个方面,将负数转换成无符号数可能会得到0[^1]。如果转换的无符号数太大以至于超过了补码能够表示的范围,可能会得到该范围的最大值。不过,对于C语言的实现来说,对这个问题的回答都是从位级角度来看,而不是从数的角度
在这里插入图片描述

比如说,考虑下面的代码:

short int v = -12345;
unsigned short uv = (unsigned short)v;
printf("v = %d, uv = %u\n",v,uv);

在一台采用补码的机器来说,上述代码会产生如下输出:
v = -12345, uv = 53191
原因如下:
首先对于有符号整型v来说,-12345在采用补码的机器上面存储的位模式为[1100 1111 1100 0111]
其次对于无符号整型uv来说,53191在采用补码的机器上面存储的位模式位[1100 1111 1100 0111]
在这里插入图片描述

还可以反过来检验:

/**十六进制表示写作0xcfc7的16位位模式既是-12345的补码表示,又是53191的无符号表示。同时注意:12345+53191 = 65536 = 2^16这个属性可以推广到给定位模式的两个数值(补码和无符号数)之间的关系。*/
#include <stdio.h>
int main()
{
    unsigned short x = 0xcfc7;
    short y = 0xcfc7;
    printf("%u\n", x);
    printf("%d\n", y);
    return 0;
}

程序输出示例:

53191
-12345

综上,强制类型转换的结果保持位值不变,只是改变了解释这些位的方式。因为由上图可知,-12345的16位补码表示与53191的16位无符号表示是完全一致的。将short强制类型转换为unsigned short改变数值[解释这些位的方式],但是不改变位表示本身
对于大多数C语言的实现,处理同样的字长的有符号数和无符号数之间相互转换的一般规则是:数值可能会改变,但是位模式不变

对于不同字长的类型,其隐式转换会复杂的多,感谢评论区@Lily_Shayi:

#include <iostream>
#include <iomanip>
using namespace std;

inline void print_uint128_t(__uint128_t x){
    if(x>9)
        print_uint128_t(x/10);
    putchar(x%10+'0');
}

inline void print_int128(__int128 x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9)
        print_int128(x/10);
    putchar(x%10+'0');
}
//参考链接:https://blog.csdn.net/shadandeajian/article/details/81843805

int main()
{
    __uint128_t a = 340282366920938463463374607431768211455;

    // 下面这条语句编译出错,__uint128_t无法使用cout直接输出
    // cout << "cout << a: " << a << endl;
    cout << "a: " << endl;
    print_uint128_t(a);
    cout << endl << endl;

    cout << "__int128: 340282366920938463463374607431768211455: " << endl;
    print_int128(340282366920938463463374607431768211455);
    cout << endl;
    cout << "__uint128_t: 340282366920938463463374607431768211455: " << endl;
    print_uint128_t(340282366920938463463374607431768211455);
    cout << endl << endl;

    unsigned long long b = 18446744073709551615;
    cout << "b: "  << endl << b << endl << endl;

    cout << "__int128: 18446744073709551615: " << endl;
    print_int128(18446744073709551615);
    cout << endl;
    cout << "__uint128_t: 18446744073709551615: " << endl;
    print_uint128_t(18446744073709551615);
    cout << endl << endl;

    cout << "__int128: b: " << endl;
    print_int128(b);
    cout << endl;
    cout << "__uint128_t: b: " << endl;
    print_uint128_t(b);
    cout << endl << endl;
    //
    cout << "__int128: -1: " << endl;
    print_int128(-1);
    cout << endl;
    cout << "__uint128_t: -1: " << endl; // **********
    print_uint128_t(-1);
    cout << endl << endl;

    cout << "int -> unsigned long long  -1: " << endl << (unsigned long long)-1 << endl << endl;

    // __uint128_t vs __uint128_t
    // 18446744073709551615 < 340282366920938463463374607431768211455 ?
    if (a < -1)
        cout << "a<-1" << endl << endl;

    // unsigned long long vs unsigned long long
    // 18446744073709551615 == 18446744073709551615 ?
    if (b == -1)
        cout << "b==-1" << endl << endl;

    // __uint128_t vs __uint128_t
    // 18446744073709551615 == 18446744073709551615 ?
    if (a == b)
        cout << "a==b" << endl << endl;

    // __int128 vs __int128
    // 18446744073709551615 > -1 ?
    if (18446744073709551615 > -1)
        cout << "un64max>-1" << endl << endl;

    // -1
    cout << (int)18446744073709551615 << endl << endl;

    // int vs int
    // -1 > -1 ?
    if ((int)18446744073709551615 > (int)-1)
        cout << "(int)18446744073709551615 > (int)-1" << endl << endl;

    // __int128 vs __int128
    // 18446744073709551615 == 18446744073709551615 ?
    if (340282366920938463463374607431768211455 == 18446744073709551615)
        cout << "un128max==un64max" << endl << endl;

    // __int128 vs __int128
    // 18446744073709551615 > -1 ?
    if (340282366920938463463374607431768211455 > -1)
        cout << "un128max>-1" << endl << endl;
    // __uint128_t// unsigned long long// int// __int128 // __int128
    cout << sizeof(a) << ' ' << sizeof(b) << ' ' << sizeof(-1)
         << ' ' << sizeof(18446744073709551615) << ' ' << sizeof(340282366920938463463374607431768211455) << endl << endl;
}

程序输出(Linux平台):

a: 
18446744073709551615

__int128: 340282366920938463463374607431768211455: 
18446744073709551615
__uint128_t: 340282366920938463463374607431768211455: 
18446744073709551615

b: 
18446744073709551615

__int128: 18446744073709551615: 
18446744073709551615
__uint128_t: 18446744073709551615: 
18446744073709551615

__int128: b: 
18446744073709551615
__uint128_t: b: 
18446744073709551615

__int128: -1: 
-1
__uint128_t: -1: 
340282366920938463463374607431768211455

int -> unsigned long long  -1: 
18446744073709551615

a<-1

b==-1

a==b

un64max>-1

-1

un128max==un64max

un128max>-1

16 8 4 16 16


截图:
在这里插入图片描述

将负数转换成无符号数可能会得到0(小端法机器)

```

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
符号无符号之间转换在C语言中是允许的。当将有符号强制转换无符号时,会发生类型转换。根据C语言的规则,这种转换是从位级角度来看的,而不是从的角度。具体来说,对于在两种形式中都能表示的值,转换后的结果保持不变。但是,如果将负转换无符号,可能会得到0。如果转换无符号太大以至于超过了补码能够表示的范围,可能会得到该范围的最大值。当发生有符号无符号之间的强制类型转换时,如果它们的长度相同,则在位级表示上并没有变化。然而,如果它们的长度不同,则会先进行长度的转换,然后再进行类型转换。\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [C中的有符号无符号之间转换](https://blog.csdn.net/fhyangchina/article/details/55250934)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [有符号无符号之间转换(2020)C](https://blog.csdn.net/qq_43656353/article/details/107557559)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ocodotial

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值