1

我有以下代码:

#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 行的比较被评估为false,但是在这种情况下有没有办法得到警告?如果不是,第 12 行和引起警告的行之间是否存在一些主要区别?char 和 unsigned char 的比较不应该得到警告有什么具体原因吗?因为至少乍一看,第 12 行在我看来比第 16 行更“危险”。

一个简短的“背后故事”:我必须将来自不同来源的代码片段放在一起。其中一些使用 char,一些使用 unsigned char。-funsigned-char可以正常工作,但我不得不避免它,而是添加适当的类型转换。这就是为什么这样的警告对我有用的原因,因为现在,如果我忘记在这种情况下添加类型转换,程序就会默默地失败。

在此先感谢,P。

4

1 回答 1

0

我相信这是由整数提升引起的。

当您处理charorshort时,C 实际所做的(这是由标准定义的,而不是由实现定义的)是int在执行任何操作之前将这些类型提升到。我认为这个理论int应该是底层机器使用的自然大小,因此是最快、最有效的大小;事实上,大多数架构会在加载字节时进行这种转换,而不会被询问。

由于两者signed charunsigned char都适合在 a 的范围内signed int,因此编译器对两者都使用它,并且比较变成了纯带符号的比较

当表达式左侧的类型不匹配时(第 10 行和第 14 行),它需要将其转换回较小的类型,但它不能,因此您会收到警告。

当您比较不匹配的指针(第 16 行)并传递不匹配的指针(第 18 行)时,整数提升不起作用,因为您实际上从未取消引用指针,因此从未比较整数(char也是整数类型,课程)。

于 2013-11-14T12:28:19.287 回答