使用%u读取签名的字符

时间:2016-04-01 07:27:07

标签: c++ c pointers char pointer-arithmetic

#include <stdio.h>

int main() {
    int i,n;
    int a = 123456789;

    void *v = &a;

    unsigned char *c = (unsigned char*)v;

    for(i=0;i< sizeof a;i++) {
        printf("%u  ",*(c+i));
    }

    char *cc = (char*)v;
    printf("\n %d", *(cc+1));

    char *ccc = (char*)v;
    printf("\n %u \n", *(ccc+1));

}

该程序在我的32位Ubuntu机器上生成以下输出。

21  205  91  7  
-51
4294967245

我能理解的前两行输出=&gt;

  • 第1行 :在内存中存储字节的顺序。
  • 第二行 :第二个字节值的有符号值(2的补码)。
  • 第3行 :为什么这么大的值?

请解释最后一行输出。为什么添加三个1的字节 因为(11111111111111111111111111001101) = 4294967245

2 个答案:

答案 0 :(得分:12)

显然你的编译器使用有符号字符,它是一个小端,双补码系统。

123456789d = 075BCD15h
Little endian: 15 CD 5B 07

因此v + 1给出值0xCD。如果将其存储在已签名的字符中,则会以带符号的十进制格式获得-51

当传递给printf时,包含值*(ccc+1)的字符-51首先被隐式类型提升为int,因为像printf这样的可变参数函数有一个规则,表明所有小整数参数都会得到提升为int默认参数促销)。在此促销期间,标志将被保留。您仍然具有值-51,但对于32位有符号整数,这将给出值0xFFFFFFCD

最后,%u说明符告诉printf将其视为无符号整数,因此最终得到4.29 bil。

这里要理解的重要部分是%u与实际类型促销无关,它只是告诉printf如何在促销后解释数据

答案 1 :(得分:8)

8位十六进制的

-51存储为0xCD。 (假设2s称赞二进制系统)

当您将printf传递给char时,会发生默认参数提升,int会提升为0xFFFFFFCD,代表0xFFFFFFCD(对于4 byte int)。

int被解释为-51unsigned int,并被解释为4294967245printf

进一步阅读:variadic function

  

请解释最后一行输出。为什么三个字节的1是   加入

这称为Default argument promotions in C function calls。当较小的有符号数被分配(转换)为较大的数字时,其符号位被复制以确保它代表相同的数字(例如1s和sign extension)。

错误char格式说明符
您正在尝试使用指定"%u"的{​​{1}}打印unsigned [int]。与printf中的转换说明符不匹配的参数是来自 7.19.6.1 第9段的未定义行为。

  

如果转换规范无效,则行为未定义。如果   任何参数都不是相应转换的正确类型   具体而言,这种行为是未定的。

使用char存储已签名的值
另外,为了确保char包含signed值,明确使用signed char作为char可能会表现为signed charunsigned char。 (在后一种情况下,您的代码段的输出可能是205 205)。在gcc中,您可以强制char使用unsigned char -funsigned-char作为<sortField name="name"/> <sortField name="city" order="Descending"/>