C/C++标准到底是如何处理char c = 255?

新手上路,请多包涵

char是signed还是unsigned由实现决定,但是char又区别于signed char和unsigned char。那么C标准和C++标准里对char c = 255到底是怎么处理的?比如在某些实现里(比如x86和x64)默认是signed,那么char c = 255就超出了signed char的表示范围,这是未定义的行为。
我现在遇到一个问题,sha256值(32字节)存在char数组里,我把数组的每个元素与0xFF进行异或,然后再把结果的每个元素与xFF进行异或,这时最终结果跟原sha256值还能保证一定一致吗?

阅读 5.7k
4 个回答

这个是编译器实现中的规定吧,为了防止这样的问题,你自己明确用无歧义的变量类型啊,比如
unsigned char
或者
unsigned INT8
或者
UINT8

我感觉没区别,因为感觉你做的这些操作并不会有unsigned和signed之间的区别


#include <stdio.h>
#include <stdint.h>


void a() {
    signed char aa = 255;
    printf("%x", aa);
}

void b() {
    unsigned char bb = 255;
    printf("%x", bb);
}

void c() {
    int8_t cc = 255;
    printf("%x", cc);
}

void d() {
    uint8_t dd = 255;
    printf("%x", dd);
}

https://godbolt.org/
我这边看上面代码里的4个函数,使用clang/gcc编译结果完全一样(4个立即数255都会编译成-1),使用msvc编译器会把255这个立即数选择性编译成255/-1,但运行结果应该也是一样的

unsigned 和 signed 的区别只是把最高的一位作为符号位判断而已。我认为如果你赋值一个溢出的常量给char变量,看编译器把这个常量转换成多少位数据,然后从低开始到第八位开始截断赋值给char变量。
我认为一致,我做过一个需求和你的差不多也是保存数据,但我用的0xFF这个32位数据,每与一次右移8位保存到char数组的char[0]char[1]char[2]char[3].

signed还是unsigned 对你的计算有影响,但对于定义来说,无论你写成signed还是unsigned都是一样的,char c = 255; 还是 unsigned char = 255; 对于计算机来说都是 0xff,所以没有超出解释范围的说法。
在看别人代码的时候,经常会看到 unsigned int a = -1; 它等价于 a= 0xffffffff,但 -1 写起来更简单。
如果你写 char c = 300; 这才叫超出范围,因为一个字节最大能表示的数是255。

对于or, and, xor 这样的逻辑运算,你可以忽略 signed 和 unsigned 的区别,结果都一样。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题