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

これは整数の昇格が原因だと思います。

charまたはを扱うときshort、Cが実際に行うこと(これは実装ではなく標準で定義されています)はint、操作を行う前にこれらの型を昇格させます。理論的には、intそれは基盤となるマシンが使用する自然なサイズであり、したがって最速で最も効率的なサイズであると考えられています。実際、ほとんどのアーキテクチャは、バイトをロードするときに、尋ねられることなくこの変換を行います。

signed charとの両方unsigned charが a の範囲内にうまく収まるためsigned int、コンパイラはそれを両方に使用し、比較は純粋な符号付き比較になります。

式の左側 (10 行目と 14 行目) に一致しない型がある場合、それを小さい型に変換する必要がありますが、変換できないため、警告が表示されます。

不一致のポインターを比較し (16 行目)、不一致のポインターを渡した場合 (18 行目)、実際にはポインターを逆参照しないため、整数の昇格は行われず、整数は比較されません (charも整数型です。コース)。

于 2013-11-14T12:28:19.287 に答える