关于在char变量中存储无符号char值时的类型安全
我有一个包含几个字符的关于在char变量中存储无符号char值时的类型安全,c,casting,type-conversion,language-lawyer,type-safety,C,Casting,Type Conversion,Language Lawyer,Type Safety,我有一个包含几个字符的char数组。我想将其中一个字符与无符号字符变量进行比较。例如: char myarr = { 20, 14, 5, 6, 42 }; const unsigned char foobar = 133; myarr[2] = foobar; if(myarr[2] == foobar){ printf("You win a shmoo!\n"); } signed char foo = -1; unsigned char bar = 255; if(foo
char
数组。我想将其中一个字符与无符号字符
变量进行比较。例如:
char myarr = { 20, 14, 5, 6, 42 };
const unsigned char foobar = 133;
myarr[2] = foobar;
if(myarr[2] == foobar){
printf("You win a shmoo!\n");
}
signed char foo = -1;
unsigned char bar = 255;
if(foo == bar){
printf("same\n");
}
这种比较类型安全吗
我从C99标准中知道char
、signed char
和unsigned char
是三种不同的类型(第6.2.5节第14段)
- 尽管如此,我是否可以安全地在
和无符号字符
之间进行转换,然后再转换回来,而不会丢失精度,也不会出现未定义(或实现定义)的行为字符
在第6.2.5节第15段中: 实现应将字符定义为具有相同的范围, 表示和行为为
有符号字符
或无符号字符
在第6.3.1.3节第3段中:
否则,新类型已签名,且无法在其中表示值;要么结果是实现定义的,要么引发实现定义的信号
我担心如果char
被定义为signed char
,那么myarr[2]=foobar
可能会导致实现定义的值无法正确转换回原始unsigned char
值;例如,一个实现可能总是导致值42
,而不考虑所涉及的无符号
值
- 这是否意味着将
值存储在同一类型的无符号
变量中是不安全的有符号
在第6.3.1.1节第1段中: --
long-long-int
的等级应大于long-int
的等级,后者应大于int
的等级,后者应大于short-int
的等级,其等级应大于签名字符的等级
--任何无符号整数类型的秩应等于相应整数类型的秩
有符号整数类型(如果有)
在第6.2.5节第8段中:
对于具有相同符号性和不同整数转换秩的任意两个整数类型
(见6.3.1.1),整数转换秩较小的类型的值范围为a
其他类型的值的子范围
在第6.3.1节第2段中:
如果int
可以表示原始类型的所有值,则该值将转换为int
;否则,它将转换为无符号整数
在第6.3.1.8节第1段中:
否则,两个操作数都将转换为无符号整数类型
对应于带符号整数类型的操作数的类型
char
的范围保证与signed char
或unsigned char
的范围相同,这两个字符都是int
和unsigned int
的子范围,因为它们的整数转换秩较小
由于整数提升规则规定在求值之前,char
、signed char
和unsigned char
至少提升为int
,这是否意味着char
可以在整个比较过程中保持其“签名性”
例如:
char myarr = { 20, 14, 5, 6, 42 };
const unsigned char foobar = 133;
myarr[2] = foobar;
if(myarr[2] == foobar){
printf("You win a shmoo!\n");
}
signed char foo = -1;
unsigned char bar = 255;
if(foo == bar){
printf("same\n");
}
- 当使用显式的
强制转换时,(无符号字符)
是否计算为假值,即使foo==bar
相当于-1
255
更新: 在第J.3.5节第1段中,关于哪些情况会导致实现定义的值和行为: --将整数转换为有符号整数类型的结果或所产生的信号 当该值无法在该类型的对象中表示时(6.3.1.3)
- 这是否意味着即使是显式转换也不安全
char
可以定义为有符号整数类型:
“这是否意味着
char
可以在整个比较过程中保持其“符号性”<代码>-1作为签名字符
将升级为签名整数
,该整数将保留其-1
值。至于无符号字符
,它在升级时也将保留其255
值,因此是的,比较将为false。如果希望它的计算结果为true,则需要显式强制转换。我已经测试了您的代码,但它没有将(有符号字符)-1
和(无符号字符)255
进行相同的比较。
您应该首先将有符号字符转换为无符号字符,因为它在操作中不使用MSB符号位
我对使用有符号字符类型进行缓冲区操作的经验不好。像你的问题这样的事情就会发生。然后确保在编译过程中打开了所有警告并尝试修复它们。这与字符的内存存储方式有关,在无符号字符中,所有8位用于表示字符的值,而有符号字符仅使用7位表示数字,第8位表示符号 例如,让我们取一个更简单的3位值(我将此新值类型称为tinychar): 通过查看此图表,您可以根据位的排列方式看到有符号和无符号tinychar之间的值差异。直到
char foo = -25;
unsigned char bar = foo;
if(foo == bar){
printf("This line of text will not be printed.\n");
}
/* binary representation prefix: 0b */
(signed char)(-25) = 0b11100111
(unsigned char)(231) = 0b11100111
unsigned foo = UINT_MAX;
signed bar = foo; /* possible implementation-defined behavior */
signed char foo = -1;
unsigned char bar = 255;
if((unsigned char)foo == bar){
printf("same\n");
}