欢迎来真孝善网,为您提供真孝善正能量书籍故事!

了解signed char与unsigned char的区别

时间:11-24 神话故事 提交错误

大家好,今天来为大家解答了解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", "不等于"); /* 结果:不等于*/

用户评论

执拗旧人

我还在学习C语言呢,这两种类型确实容易混淆。

    有14位网友表示赞同!

早不爱了

说白了就是一个可以负数,一个只能是正数,对吧?

    有18位网友表示赞同!

莫阑珊

平时编程都还好,遇到题目要分析内存的时候就有点懵逼。

    有6位网友表示赞同!

箜明

我记得unsigned char可以用做位运算啊,那signed char呢?

    有10位网友表示赞同!

景忧丶枫涩帘淞幕雨

什么时候用哪个类型我会先记住这个区别,谢谢!

    有18位网友表示赞同!

别悲哀

这玩意儿对空间效率好像有讲究吧?

    有14位网友表示赞同!

一别经年

学习这些基础知识总是很有必要的,理解了之后编程会更得心应手。

    有12位网友表示赞同!

单身i

想问一下这两种类型的取值范围有多大啊?

    有11位网友表示赞同!

心已麻木i

感觉signed char比 unsigned char多了一个方向,对程序设计空间会更大一些吧?

    有19位网友表示赞同!

鹿叹

之前见过用char表示布尔值的写法,会不会影响 signed/unsigned 的区别?

    有16位网友表示赞同!

情深至命

学习计算机基础真是太重要了,这些细节都能学到!

    有11位网友表示赞同!

强辩

我看下教程好像说signed char和 unsigned char在一些语言里也有别的命名方式,是真的吗?

    有20位网友表示赞同!

陌颜

我记得之前学习的时候说char默认是signed类型,是吗?

    有12位网友表示赞同!

半世晨晓。

这个真题题啊!我每次都把它们搞混淆了。

    有8位网友表示赞同!

心安i

以后遇到编程题的时候可以试试用这两种类型的区别来优化代码哈!

    有18位网友表示赞同!

颓废人士

这种知识点确实很基础,但掌握好非常有助于提升编程能力。

    有18位网友表示赞同!

一样剩余

看来还是需要再温习一遍C语言基本的数据类型了!

    有19位网友表示赞同!

入骨相思

这篇文章写的真的很有帮助,让我对signed char 和 unsigned char 的区别有更清晰的理解!

    有13位网友表示赞同!

【了解signed char与unsigned char的区别】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活