大家好,今天来为大家解答了解signed char与unsigned char的区别这个问题的一些问题点,包括也一样很多人还不知道,因此呢,今天就来为大家分析分析,现在让我们一起来看看吧!如果解决了您的问题,还望您关注下本站哦,谢谢~
#includevoid foo(有符号字符sc, 无符号字符uc) {
if (sc=="x85") printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果: 等于*/
if (uc=="x85") printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果:不等于*/
if (sc==0x85) printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果:不等于*/
if (uc==0x85) printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果: 等于*/
}
int main(int argc, char * argv[]) {
有符号的char sc="x85";
无符号字符uc="x85";
foo(uc, sc);
返回0;
}运行结果为
平等的
不等于
不等于
平等的执行环境是Darwin gcc-4.2
$ uname -a
达尔文本地主机15.6.0 达尔文内核版本15.6.0: 4 月11 日星期二16:00:51 PDT 2017; root:xnu-3248.60.11.5.3~1/RELEASE_X86_64 x86_64
$ 海湾合作委员会-v
配置为: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10 .12.sdk/usr/include/c++/4.2.1
Apple LLVM 版本8.0.0 (clang-800.0.42.1)
目标: x86_64-apple-darwin15.6.0
线程模型: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin 查看比较语句的汇编代码:
if (sc=="x85"):
movsbl -1(%rbp), %esi
cmpl $-123,%esi
jne LBB0_2
if (uc=="x85"):
movzbl -2(%rbp), %eax
cmpl $-123,%eax
jne LBB0_5
如果(sc==0x85):
movsbl -1(%rbp), %eax
cmpl $133, %eax
jne LBB0_8
如果(uc==0x85):
movzbl -2(%rbp), %eax
cmpl $133, %eax
jne LBB0_11首先解释一下上面用到的几条指令。
movzbl:
将零扩展字节移至长整型。
目标操作数的低8 位被源操作数替换。最高24 位设置为0。
movsbl:
将符号扩展字节移至长整型。
cmpl:
逻辑比较意味着它不查看符号并将操作数视为无符号整数。
如果arg1 是立即数,它将被符号扩展为arg2 的长度。我们来分析一下各个对比语句
if (sc=="x85"): 指令说明movsbl -1(%rbp), %esi 将参数sc 的值移至寄存器esi,并符号扩展为0xffffff85cmpl $-123, %esi。本说明有两个部分。 1. 将立即数($-123) 展开为0xffffff85, 2. jne LBB0_2 进行无符号比较,比较结果相同if (uc=="x85") : 指令说明movzbl -2(%rbp), %eax 将参数sc 的值移至寄存器esi,并将0 扩展为0x00000085cmpl $-123。 %esi 指令有两部分操作: 1. 将立即数($-123) 展开为0xffffff85, 2. 进行无符号比较jne LBB0_2 比较结果不同if (sc==0x85) 指令说明movsbl -1(% rbp), %eax 将参数sc 的值移至寄存器esi,并进行符号扩展至0xffffff85cmpl $133, %esi 该指令分为两部分操作: 1. 将立即数($133) 扩展至0x00000085, 2. 进行无符号比较jne LBB0_2 与比较结果不一样if (uc==0x85) 指令说明movzbl -1 (%rbp), %eax 改变参数sc 将值移至寄存器esi,做0 扩展为0x00000085cmpl $133, %esi 此指令: 的操作分为两部分: 1. 将立即数($133)展开为0x00000085, 2. 对LBB0_2 进行无符号比较,比较结果相同。需要注意的一件事是,为什么汇编代码中使用的0x85这个“常量”有的地方使用$133,而有的地方使用$-123?这与x64指令系统无关,它是gcc编译器处理的结果。
因为在C语言层面,虽然"x85"和0x85在很多情况下可以互换使用,但还是有区别的。 "x85"是一个字符,字符类型默认是有符号的,所以即使表示为16进制都是0x85,但是用十进制表示的含义是不同的。字符"x85"=-123,而不是133 (8*16+5);0x85 是一个没有符号的数字常量。对于展开题,用十进制表示的值为133。
综上所述
默认字符类型是有符号字符。在将字符类型与其他类型的数据进行比较时,必须充分考虑扩展问题,无论是有符号扩展还是无符号扩展。
Darwin环境下gcc编译器会报两个警告
$gcct.c
test.c:5:12: warning: 常量-123 与“unsigned char”类型表达式的比较始终为false
[-Wtautological-constant-out-of-range-compare]
if (uc=="x85") printf("%sn", "等于"); else printf("%sn", "不等于"); /* 不等于*/
~~^~~~~~~
test.c:7:12: warning: 常量133 与“signed char”类型表达式的比较始终为false
[-Wtautological-constant-out-of-range-compare]
if (sc==0x85) printf("%sn", "等于"); else printf("%sn", "不等于"); /* 不等于*/
~~ ^ ~~~~
生成2 个警告。在Linux x64 gcc环境下就更神奇了。警告信息直接丢弃。当关闭优化开关(gcc -S -O0)时,生成的汇编代码如下:
.rodata 节
.LC0:
.string "不等于"
。文本
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
推q%rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
子q $16,%rsp
movl %edi, %edx
movl %esi, %eax
movb %dl, -4(%rbp)
movb %al, -8(%rbp)
不
movl $.LC0, %edi
看涨期权
不
movl $.LC0, %edi
看涨期权
离开
.cfi_def_cfa 7, 8
雷特
.cfi_endproc
.LFE0:
.size foo,-foo 可以看到,在函数foo中,比较指令被丢弃了,甚至字符串"equal"也被丢弃了。该函数直接打印两行“不等于”($.LC0),无论输入参数的值是什么。这相当于foo 函数相当于:
void foo(有符号字符sc, 无符号字符uc) {
printf("%sn", "不等于"); /* 不等于*/
printf("%sn", "不等于"); /* 不等于*/
}换一种方式写,function foo 会输出什么结果?
void foo(有符号字符sc, 无符号字符uc) {
if (sc==-123) printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果: 等于*/
if (uc==-123) printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果:不等于*/
if (sc==133) printf("%sn", "等于"); else printf("%sn", "不等于"); /* 结果:不等于*/
【了解signed char与unsigned char的区别】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
我还在学习C语言呢,这两种类型确实容易混淆。
有14位网友表示赞同!
说白了就是一个可以负数,一个只能是正数,对吧?
有18位网友表示赞同!
平时编程都还好,遇到题目要分析内存的时候就有点懵逼。
有6位网友表示赞同!
我记得unsigned char可以用做位运算啊,那signed char呢?
有10位网友表示赞同!
什么时候用哪个类型我会先记住这个区别,谢谢!
有18位网友表示赞同!
这玩意儿对空间效率好像有讲究吧?
有14位网友表示赞同!
学习这些基础知识总是很有必要的,理解了之后编程会更得心应手。
有12位网友表示赞同!
想问一下这两种类型的取值范围有多大啊?
有11位网友表示赞同!
感觉signed char比 unsigned char多了一个方向,对程序设计空间会更大一些吧?
有19位网友表示赞同!
之前见过用char表示布尔值的写法,会不会影响 signed/unsigned 的区别?
有16位网友表示赞同!
学习计算机基础真是太重要了,这些细节都能学到!
有11位网友表示赞同!
我看下教程好像说signed char和 unsigned char在一些语言里也有别的命名方式,是真的吗?
有20位网友表示赞同!
我记得之前学习的时候说char默认是signed类型,是吗?
有12位网友表示赞同!
这个真题题啊!我每次都把它们搞混淆了。
有8位网友表示赞同!
以后遇到编程题的时候可以试试用这两种类型的区别来优化代码哈!
有18位网友表示赞同!
这种知识点确实很基础,但掌握好非常有助于提升编程能力。
有18位网友表示赞同!
看来还是需要再温习一遍C语言基本的数据类型了!
有19位网友表示赞同!
这篇文章写的真的很有帮助,让我对signed char 和 unsigned char 的区别有更清晰的理解!
有13位网友表示赞同!