char、signed char 和 unsigned char 的区别
ANSI C 提供了3种字符类型,分别是char、signed char、unsigned char.而不是像short、int一样只有两种(int默认就是signed int).
三者都占1个字节(1 byte),因此:
signed char取值范围是 -128 到 127(有符号位)
unsigned char 取值范围是 0 到 255
这个大家都很清楚!!
但是char 呢?范围是多少?
答案是:不一定!!!
我们先看一下大师们怎么说的:
(Thinking in C++ 2nd):
signed is the default and is only necessary with char; char may or may not default to signed. By specifying signed char, you force the sign bit to be used.
译文:有符号类型是默认(指的是对于其他整型如int等来说)的类型并且仅对于char来说才是必须的。char有可能 是signed也有可能是unsigned(我想这可能取决于编译器的具体实现)。但通过显式地指定一个char为signed,你就迫使其成为有符号的 字符型。
我的看法是:
我们首先从这些类型的用处开始想起!
char是用来声明字符的!
而signed char和unsigned char是用来声明数值的,和int与unsigned int一样,只是其占据的空间少(这在手机等空间有限的嵌入式系统中尤其有效!),表示的范围有限。
那么char在各个编译器中是怎样实现的?
c标准中对此是 Implementation Defined,就是未明确定义,由具体的编译器明确定义。
但是一般都是用signed char或unsigned char来实现char的,因为这三种类型的对象在存储介质中的表现形式是一样的(都是一个占8bit的01串,只是解析的时候不同)。
至于到底是signed char还是unsigned char,各个编译器不同!!VC编译器、x86上的GCC都把char定义为signed char,而arm-linux-gcc却把char定义为 unsigned char.
这样一来,在代码移植(困扰我们程序员的一个问题)上就会出现问题,举个最简单的例子:
char a = 0xb6;
if ( a == 0xb6) puts("hello world !");
在vc 或 x86的gcc 上,都是不会打印出 hello world! 的。
用 arm-linux-gcc 编译,在arm板上,是可以打印出hello world ! 的。
我们再变化一下:
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if ( a == 0xb6) puts("a");
if ( b == 0xb600) puts("b");
if ( c == 0xb6000000) puts("c");
在vc 或 x86的gcc 上,只会打印出 c 。用 arm-linux-gcc 编译,在arm板上,是可以打印出 a 和 c 。是不是发现了什么了呢?
首 先,介绍 Integral Promotion(整数提升) 。通俗点说,c在处理整型(char short int)时,都会自动提升为int(如果int范围不够,则提升成 unsigned int)。比如 “a == 0xb6”,首先0xb6会当一个int来处理,变为0x000000b6(关于常量,后面还会仔细说明)。a 会提升为int ,假如 char 被定义为有符合的,那么 a 为负数,因为最高位为1,所以 a会提升为 0xffffffb6。假如 char 被定义为无符号的,那么a会提升为 0x000000b6 。
即,在vc 或 x86的gcc 上,(a == 0xb6) 会变为 (0xffffffb6 == 0x000000b6) ,而在 arm-linux-gcc 上,变为(0x000000b6 == 0x000000b6)。
对于 short,因为c标准明确规定 不加关键字,就代表有符号数。所以,无论在什么编译器上 b == 0xb600 都会变成 0xffffb600 == 0x0000b600 。
对于 int,本身是int,也就不用 Integral Promotion 了,所以 c == 0xb60000 中 ,c不做任何处理,直接从内存中读出来,即 0xb60000 == 0xb60000。
最 后,简单说一下常量。用八进制(0开头)或十六进制(0x开头)表示的常量,他们都会当成无符号数处理! 另外 像 char a = 0xb6; 这句就有两个 Implementation Defined,一个是char带不带符号,另外一个是,假如char为有符号, 0xb6 会当int 0x000000b6 处理,把这个int 变为 有符号的 char 有溢出,会有问题,0xb6本为正数,赋值到a中却变为负数,具体要怎么处理,c对此也是 Implementation Defined。
1.
C++中内置数据类型分为两类:整数、浮点数。 对于不同的整数类型来说,比如int,unsigned int,有这么两句话:
int a=11;
unsigned int b=11;
我们可以看对应的汇编代码:
00BC1505 mov dword ptr [b],0Bh
我们不难发现,数据11(0x0B),在内存中,无论是int还是unsigned int,都是0x0B,存储是一样的,只是解析不同。
2.
C++中的 Integral Promotion发生在算术表达式中(有运算符如+ ~等),其他情况下比如cout语句我要输出一个字符: cout<<a;这个时候不会提升。
3.
4.本文原作者说常量是无符号数,这种说法值得商榷,《C++ primer》中说过,20,024,0x14的类型是int或者long!!!我想原作者的意思是这样的:
int a=-1; 这句话执行的结果是 a里面存放着:0x FFFFFFFF,也就是-1对应的补码
int a=1 ; 这句话执行的结果是 a里面存放着:0x 00000001,也就是1对应的补码
int a=0xF7;这句话执行结果是 a里面存放着:0x 000000F7,a的低位放着F7,其他高位全部置为0;看起来像是oxF7是无符号数才会按0扩展,但事实上不是这个原因。
本质原因是汇编的mov指令:
mov ax,-1;其实汇编器最终会解释成:mov ax,FFFF
mov ax,F7H;其实汇编器最终会解释成: mov ax,00F7
所以需要注意: 常量-1,3,0xf4都是int或者long型的。
可以用下面代码小小测试:
cout<<a+0x1;
以及
cout<<a+0x1u;
运行一下,不难看出,0x1被当做int来处理,ox1u才是unsigned int型的。
比较好的参考资料:
这个网址里面对各种数据类型,以及整形提升,Usual Arithmetic Conversion做了非常详细的说明。
char、signed char 和 unsigned char 的区别的更多相关文章
- C语言char*字符串数组和unsigned char[]数组的相互转换
#include <iostream> #include <string> using namespace std; void convertUnCharToStr(char* ...
- C 中 char、signed char 和 unsigned char 的区别
C 中 char.signed char 和 unsigned char 的区别 来源:http://bbs.chinaunix.net/thread-889260-1-1.html 参考:https ...
- signed char、unsigned char
什么是无符号char类型?与常见的char类型有何不同? 在c++中有三种不同的字符类型:char,signed char,unsigned char.如果要应用与文本字符,就使用不加限制的char类 ...
- 关于 char 和 unsigned char 的区别
首先卖个关子: 为什么网络编程中的字符定义一般都为无符号的字符? char buf[16] = {0}; unsigned char ubuf[16] = { 0 }; 上面两个定义的区别是: ...
- 图像处理中像素点的问题:unsigned char 和 char
以前在做图像处理的时候,一直不太在意这个问题,对图像每个像素点的灰度值,总是认为char也可,unsigned char也可.尽管它们都是8位,但是表示的数的范围却不相同:char: -128~127 ...
- QString unsigned char* 的转换
QString -> unsigned char* : QString str = "ABCD"; int length = str.length(); unsigned ...
- char , unsigned char 和 signed char 区别
ANSI C 提供了3种字符类型,分别是char.signed char.unsigned char.char相当于signed char或者unsigned char,但是这取决于编译器!这三种字符 ...
- char、signed char、unsigned char的区别总结。
转载地址:http://hi.baidu.com/thewillreigns/blog/item/67e665c4296e69c038db492d.html char 和 unsigned char是 ...
- char, signed char, and unsigned char in C++
关于这三者的区别stackoverrflow里有一个答案是这样说的: 3.9.1 Fundamental types [basic.fundamental] 1 Objects declared as ...
随机推荐
- plsql developer连接64位Oracle11g的解决方法
1)安装Oracle 11g 64位 2)安装32位的Oracle客户端( instantclient-basic-win32-11.2.0.1.0)下载地址:http://www.oracle.co ...
- Enze Third day(c#中选择结构【if...else】)
哈喽,又到了我总结课堂知识的时间了.今天在云和学院学的是C#中的“选择结构”下的If语句.下面就来总结一下今天所学的吧. 理论:If语句是最常用的选择结构语句.它主要根据所给定的条件(常由关系表达式和 ...
- 自定义cell时,在宽的手机上显示太窄解决办法
1.工程设置要如下:见第二个红框,清除launch screan file 后面的内容 2.自定义的cell要设置auto layout 和size clases
- mysql性能调优与架构设计(一)商业需求与系统架构对性能的影响
这里我们就拿一个看上去很简单的功能来分析一下. 需求:一个论坛帖子总量的统计附加要求:实时更新 在很多人看来,这个功能非常容易实现,不就是执行一条SELECT COUNT(*)的Query 就可以得到 ...
- [LeetCode]题解(python):015-3Sum
题目来源: https://leetcode.com/problems/3sum/ 题意分析: 这道题目是输入一个数组nums.找出所有的3个数使得这3个数之和为0.要求1.输出的3个数按小到大排序, ...
- Python之路:Python简介
Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间他为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承 ...
- Qt Creator error: LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
Qt Creator error: LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 治标又治本的解决方法: 找到在 { C:\Windows\Microsoft.NET\Fra ...
- kinect for windows - DepthBasics-D2D详解之一
Depth在kinect中经常被翻译为深度图,指的是图像到摄像头的距离,这些距离数据能让机器知道物理距离有多远.kinect通过两个红外摄像头来实现这个功能的.在这个例子里,就实现了深度图的提取和现实 ...
- GDKOI2016
天若有情天亦老 月若无恨月常圆 Day1 score cardcaptor AAAAAAAATT protal WWWWWWWWWW treasurehunt AAAAWXXXXX map AAATT ...
- iOS UILabel 使用姿势大全(标红关键字)
一.初始化 ? 1 2 3 UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 40, 120, 44)]; ...