我有以下代码:
#include <stdlib.h>
#include <stdio.h>
void test(unsigned char * arg) { }
int main() {
char *pc = (char *) malloc(1);
unsigned char *pcu = (unsigned char *) malloc(1);
*pcu = *pc = -1; /* line 10 */
if (*pc == *pcu) puts("equal"); else puts("not equal"); /* line 12 */
pcu = pc; /* line 14 */
if (pcu == pc) { /* line 16 */
test(pc); /* line 18 */
}
return 0;
}
如果我使用gcc版本4.6.3(Ubuntu / Linaro 4.6.3-1ubuntu5)(但不限于此特定版本)使用选项进行编译
gcc a.c -pedantic -Wall -Wextra -Wsign-conversion -Wno-unused-parameter; ./a.out
我收到以下警告
test.c: In function ‘main’:
test.c:10:21: warning: conversion to ‘unsigned char’ from ‘char’ may change the sign of the result [-Wsign-conversion]
test.c:14:13: warning: pointer targets in assignment differ in signedness [-Wpointer-sign]
test.c:16:17: warning: comparison of distinct pointer types lacks a cast [enabled by default]
test.c:18:17: warning: pointer targets in passing argument 1 of ‘test’ differ in signedness [-Wpointer-sign]
test.c:4:6: note: expected ‘unsigned char *’ but argument is of type ‘char *’
not equal
g警告/错误类似 . 我希望我理解为什么第12行的比较被评估为假,但在这种情况下是否有任何方法可以得到警告?如果没有,第12行和导致警告的行之间是否存在一些主要区别?有没有具体的理由为什么char和unsigned char的比较不值得发出警告?因为至少乍一看,第12行似乎比我更多"dangerous"第16行 .
简短"story behind":我必须将各种来源的代码拼凑起来 . 其中一些使用char,其中一些使用unsigned char . -funsigned-char
会正常工作,但我不得不避免它,而是添加正确的类型转换 . 这就是为什么这样的警告对我有用,因为现在,如果我忘记在这种情况下添加类型转换,程序将默默地失败 .
提前谢谢,P .
1 回答
我相信这是整数推广引起的 .
当您处理
char
或short
时,C实际执行的操作(这是由标准定义的,而不是实现)是在执行任何操作之前将这些类型提升为int
. 我认为,该理论认为int
应该是底层机器使用的自然尺寸,因此是最快,最有效的尺寸;实际上,大多数体系结构都会在加载字节时进行此转换而不会被询问 .由于
signed char
和unsigned char
都适合signed int
的范围,编译器会将其用于两者,并且比较变为纯符号比较 .如果表达式的左侧有不匹配的类型(第10行和第14行),那么它需要将其转换回较小的类型,但它不能,因此您会收到警告 .
当您比较不匹配的指针(第16行)并传递不匹配的指针(第18行)时,整数提升不起作用,因为您实际上从未取消引用指针,因此不会比较整数(
char
也是整数类型,当然) .