web-dev-qa-db-ja.com

C ++が文字の配列に符号付きまたは符号なしの文字を受け入れないのはなぜですか

私はVisual Studio 2017のネイティブモードでC++を使用しています。そのコンパイラーは以下のステートメントを問題なくコンパイルします。

const char * AnArrayOfStrings[]  = {"z1y2x3w4", "Aname"};

ただし、上記のステートメントを変更して、charが符号付きまたは符号なしであることを指定すると、コンパイラーはC244エラーを発行します。たとえば、次のステートメントはnotコンパイルします。

const signed   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};

const unsigned char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};

Charの符号を明示的にすると、コンパイラがステートメントのコンパイルを拒否する理由がわかりません。

私の質問は:コンパイラがこれらのステートメントのコンパイルを拒否したために見逃してしまった正当な理由はありますか?

ご協力ありがとうございます(C++のドキュメントであるStackOverflowで調査を行い、Googleを使用し、自分で答えを見つけるために数十のC/C++の本について相談しましたが、それでも理由がわかりません。)

21
ScienceAmateur

"z1y2x3w4"const char[9]であり、const char*からconst signed char*への暗黙的な変換はありません。

reinterpret_castを使用できます

const signed char * AnArrayOfStrings[]  = {reinterpret_cast<const signed char *>("z1y2x3w4"),
                                           reinterpret_cast<const signed char *>("Aname")};
15
Gaurav Sehgal

上記のコードをコンパイルすると

const signed   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};  

cでgccを使用してオプション-Wallを使用すると、次の警告が表示されます

test.c:5:49: warning: pointer targets in initialization differ in signedness [-Wpointer-sign]
  const unsigned   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
                                                 ^
test.c:5:49: note: (near initialization for 'AnArrayOfStrings2[0]')
test.c:5:61: warning: pointer targets in initialization differ in signedness [-Wpointer-sign]
  const unsigned   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};  

AnArrayOfStrings2"z1y2x3w4"の要素のタイプは異なります。 AnArrayOfStrings2[0]const signed char *タイプであり、"z1y2x3w4"const char[9]タイプです。
C++では同じコードでエラーが発生します。 C++で機能させるには、明示的なキャストが必要です。


理由を説明する

const char * AnArrayOfStrings[]  = {"z1y2x3w4", "Aname"}; 

簡単な例をとります

const char c[] = "asc";
const char *p1 = c;           // OK
signed const char *p2 = c;    // Error
unsigned const char *p3 = c;  // Error

上記のスニペットの2行目で、cconst char *に変換され、p1cは互換性のある型になります。
3行目では、p2cのタイプに互換性がなく、コンパイラーはC++でエラー(Cの警告)を発生させます。同じことが4行目でも起こります。

intタイプの別の例を考えます

const int i[] = {1,2,3};
const int *ii = i            // OK
signed const int *si = i;    // OK
unsigned const int *usi = i; // Error  

最初の2つのポインタ初期化は、指定子なしでintとして機能しますが、signed intと同等です(ただし、charには当てはまりません)。したがって、型に互換性があります。 const int *またはsigned const int *unsigned const int *と互換性がないため、最後のケースで初期化は失敗します。

3
haccks