3

char **vsについては知っていますが ( c faqconst char **で説明されているように)、配列へのポインターを使用してこれを行うと、配列自体の内容が実際に変更されるというシナリオは見当たりません。

私のコード:

void fun(const char (*p)[6])
{
    printf("%s", p[0]);
}

int main(int argc, char *argv[])
{
    char a[6] = "hello";
    char (*c)[6];

    c = &a;

    fun(c);
}

gcc でコンパイルすると、以下の出力が得られます。

test.c:17:9: warning: passing argument 1 of 'fun' from incompatible pointer type
test.c:5:10: note: expected 'const char (*)[6]' but argument is of type 'char (*)[6]'

ここでの質問は何らかの形で関連していますが、これまでのところ回答がありません。コンパイラがパラノイアになっているだけで、警告を取り除く唯一の方法は明示的にキャストすることですか? それとも、何かがうまくいかない可能性は本当にありますか?

4

3 に答える 3

3

const 変換は、標準のセクション 6.5.16.1 (1) でカバーされています。

  • 両方のオペランドは、互換性のある型の修飾されたバージョンまたは修飾されていないバージョンへのポインターであり、左側が指す型には、右側が指す型のすべての修飾子があります。

この場合、例を変更するとわかるように、残りの要件は明らかに保持されているように見えますTchar [6]

int main(int argc, char *argv[])
{
    typedef char c6[6];
    c6 a = "hello";
    const c6 *p = &a;
}

しかし、これは実際には当てはまりません!これは 6.7.3 (8) と交差します。

配列型の指定に型修飾子が含まれている場合、配列型ではなく要素型がそのように修飾されます。

したがってconst c6 *、実際にはタイプに名前を付けconst char (*)[6]ます。つまり、 const char の array[6] へのポインターであり、 char のconst array[6] へのポインターではありません。

次に、LHS は typeconst char[6]を指し、RHS はtype を指しchar[6]ますが、これらは互換性のない型であり、単純な代入の要件は成り立ちません。

于 2012-06-27T16:23:10.957 に答える
3

単なるC言語仕様の癖です。別の例として、char **toconst char *const *変換も const-correctness の観点からは安全ですが、C では禁止されています。

この const-correctness ルールの癖は C++ 言語で「修正」されましたが、C はこの点で元の仕様に固執し続けています。

于 2012-06-27T17:29:34.040 に答える
-1

実際、理由はよく似ています (char ** と配列のポインター)。

あなたがやろうとしていることについては、以下で十分です(そしてそれは機能します):

void fun(const char *p)
{
    printf("%s", p);
}

int main(int argc, char *argv[])
{
    char a[6] = "hello";
    char *c;

    c = a;

    fun(c);
}

あなたがやろうとしていることで、次のように値を変更して目的を無効にすることができます(単なる例):

void morefun(const char *p[6])
{
    char d;
    char *p1 = &d;
    p[1] = p1;
    *p1 = 'X';
    printf("\nThe char is %c\n", *p[1]);
}

int main(int argc, char *argv[])
{
    const char *d[6];

    morefun(d);
}
于 2012-06-27T16:48:46.820 に答える