3

我知道char **vsconst char **的事情(如c faq中所述),但我看不到任何使用指向数组的指针这样做会导致数组本身的某些内容被实际修改的情况。

我的代码:

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

标准第 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 指向 type const char[6], RHS 指向 type char[6],它们是不兼容的类型,简单赋值的要求不成立。

于 2012-06-27T16:23:10.957 回答
3

这只是 C 语言规范的一个怪癖。再举一个例子,从 const 正确性的角度来看, char **toconst char *const *转换也是安全的,但在 C 中是禁止的。

这种 const 正确性规则的怪癖在 C++ 语言中是“固定的”,但 C 在这方面继续坚持其原始规范。

于 2012-06-27T17:29:34.040 回答
-1

实际上原因非常相似(char ** vs. 数组指针)。

对于您要执行的操作,以下内容就足够了(并且有效):

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 回答