char十六进制转义序列和十六进制数之间的差异

时间:2018-03-07 22:36:45

标签: c hex

为什么'\ x90'和0x90彼此不同。据我所知,一个是十六进制转义序列,另一个是十六进制数。但是,如果我将它们转换为十进制,我得到144,这应该是'\ x90'和0x90的值。另外,书中说'\ x90'是负值,而0x90是正值。

据我所知,char只有1个字节,int是4,所以我们得到

char '\x90' = 1001 0000 ( 1 byte,8 bits)
int 0x90 = 1001 0000 0000 0000 0000 0000 0000 0000 (4 byte,32 bits)

我仍然无法理解为什么char x90是负数并导致差值而不是int 0x90。

我的问题不是关于char签名和未签名的问题,虽然这与我的问题有关,但我问的是这些字符的值是什么..

5 个答案:

答案 0 :(得分:3)

在C '\x90'0x90都是int个常量文字,但如果char类型已签名且有8位,则它们可能具有不同的值。在这种情况下,'\x90'的值为-112,而0x90的值始终为144

C标准规定了这一点:

  

6.4.4.4字符常量。

     

§10整数字符常量的类型为int。包含映射到单字节执行字符的单个字符的整数字符常量的值是解释为整数的映射字符的表示的数值。包含多个字符(例如,'ab')或包含未映射到单字节执行字符的字符或转义序列的整数字符常量的值是实现定义的。如果整数字符常量包含单个字符或转义序列,则其值是当类型为char的对象的值为单个字符或转义序列的对象转换为类型int时生成的值

因此,如果'\x90'类型默认签名或宽于8位,则字符常量(int)(char)0x90的值为144char。否则,它的值为-112,就像你的系统一样。

答案 1 :(得分:3)

char是1字节= 8位。如果我们认为它是"未签名" (只有正数)然后0x90 = 144,这没有问题。

char不是unsigned。意味着保留一位表示正或负(符号位)。因此,仅使用7位来表示最大正数。 2 ^ 7 = 128.当您尝试将0x90分配给char时,它因此大于最大正值。这是签名溢出和未定义的行为。

大多数实现只会转换为底片,因此它变为-128 - (128-144)= -128 + 16 = -112。

这些位可能相同,但解释不是。

(免责声明:7位中你可以容纳的实际最大正值是127,我说的是我说的,因为它是最直观的意义.0是必须考虑的值之一,所以真正的公式是2 ^ N-1,其中N是比特数。考虑1比特;即使2 ^ 1 = 2,最大值也是1)

答案 2 :(得分:3)

  

为什么'\ x90'和0x90彼此不同(?)

第一个是转义序列,第二个是整数常量。它们具有相同的价值和类型。

  

我无法理解为什么char x90是负数并导致差值而不是int 0x90。

分配给char时,它们都具有相同的值。

'\x90'0x90144都是C中的整数常量。所有3都具有相同的类型,int和相同的值: 144。

char的行为与signed charunsigned char相同。显然在OP的情况下,它的作用类似signed char,范围为[-128 ... 127]。

考虑char ch = 144;

分配144,超出OP的char范围会导致实现定义的行为。这意味着实现可以执行各种操作,例如分配最大值,就像ch = 127;一样。最常见的实现定义行为是重复加/减256,直到总和在范围内。这是144-256 - > -112。

将144视为8位unsigned char而-112视为8位签名 char时,它们都具有相同的位模式1001 0000

答案 3 :(得分:2)

两者代表相同的价值。区别在于它们的使用位置。

\x90是一个字符常量,类型为char。在单引号或双引号内需要此序列。 0x90是类型int的十六进制整数常量,不在引号内使用。

对于正/负,整数常量的类型为int,除非它们具有表示类型的后缀。由于0x90符合int的范围,因此它具有正值。如果您将其分配给char类型的变量,则该值位于char范围之外,并以实现定义的方式进行转换。

同样,转义序列\x90的类型为unsigned char。如果在'\x90'等字符常量中使用,则会将其转换为char,但该值超出char范围,因此会再次转换。

例如:

int a = 0x90;           // valid, has value 144
int b = '\x90';         // valid, has value -114
char c = 0x90;          // invalid, value out of range
char d = '\x90';        // invalid, same as above
unsigned char e[] = "\x90\x90";  // valid, string containing two bytes
char f[] = "\x90\x90";  // invalid, string containing two bytes but values are out of range
char g = \x90;          // invalid, compile error
char h = "0x90"         // valid, but contains the characters '0', 'x', '9', '0'

答案 4 :(得分:1)

这里没有看到你的代码是一种可能性:

char c = '\x90' // 1001 0000 in binary
int i  = 0x90   // 1001 0000 in binary

如果你做这样的事情

i = (int) c;    // i is ffffff90
                // casting is not necessary in C but this is just for this example

因为符号(int和char中最左边的位)继续向左填充空格。

编辑: 所以char是8位宽int是32位宽。所以当你转移char int时,int最右边的位副本就是这样     当你将它复制到int时,char c是 1 001 0000(0x90),按照约定值是1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1 001 0000 (0xffffffffffffff90)因为粗体1被复制到左边从而得到负值。

根据规则intchar,最左边的位设置为1是负数,因此在char c = 0x90`c'是负面的