const char * 与 const char ** 函数参数

标签 c gcc-warning

我已经阅读了 Why does passing char** as const char** generate a warning? ,但我仍然很困惑。

我有这样的印象(显然是错误的):函数声明中的 const 本质上是一个 promise ,即该函数不会修改您标记为 const 的内容。因此传入 const 或非 const 参数就可以了。但这:

#include <stdio.h>

extern void f1 ( const char * cc );
extern void f2 ( const char ** ccc );

int main ( void ) {
    char            c1[]    = "hello";
    const char *    c2      = "hello";
    char *          c3      = NULL;
    char **         v1      = NULL;
    const char **   v2      = NULL;

    f1( c1 );               /* ok */
    f1( c2 );               /* ok */
    f1( c3 );               /* ok */
    f1( "hello, world" );   /* ok */
    f2( v1 );               /* compiler warning - why? */
    f2( v2 );               /* ok */
    return 0;
}

如此警告:

$ cc -c -o sample.o sample.c sample.c: In function 'main': sample.c:17:
warning: passing argument 1 of 'f2' from incompatible pointer type
sample.c:4: note: expected 'const char **' but argument is of type 'char **'

最佳答案

标准禁止这样做,因为这会违反对象的常量性。考虑:

const char ch = 'X';
char* ch_ptr;
const char** ch_pptr = &ch_ptr; // This is not allowed, because...

*ch_pptr = &ch;
*ch_ptr = 'Q'; // ...this will modify ch, which should be immutable!

此行之后:

const char** ch_pptr = &ch_ptr;

*ch_pptrch_ptr 产生相同的值(地址),但它们具有不同的类型(const char*字符*)。然后,您使用 ch_pptr 指向 const 对象,这会自动导致 ch_ptr 指向相同的内存位置。通过这样做,您允许对最初声明为常量的对象进行任何修改(使用ch_ptr)。

这个错误非常微妙,但是过了一段时间,您应该能够理解为什么它可能很危险。这就是为什么它是不允许的。


Yes, but why is not putting the const in the function declaration the "promise" that the function does not do that sort of evil?

因为它以相反的方式工作——函数,做完全合法的事情可能会引入无效的行为。看一下这段代码:

static const char* sample_string = "String";

void f2 (const char ** ccc)
{
    *ccc = sample_string; //Perfectly valid - function does not do any "evil" things
}

int main ( void )
{
    char** v1 = NULL;

    f2(v1); // After this call, *v1 will point to sample_string

    (*v1)[0] = 'Q'; // Access violation error

    return 0;
}

关于const char * 与 const char ** 函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32096734/

相关文章:

c++ - 获取从另一个地址指向的地址

c++ - 将 GLSL 转换为 C 或 C++

c - 是否有任何 C 标准中定义的通用 printf-ish 例程

c++ - 将 'const char *' 传递给类型为 'char *' 的参数会丢弃限定符

c - 查找二维圆锥形状的网格点

iphone - 为什么以及何时应该在 iOS 应用程序中使用 C/C++ 代码?

C:不会创建.eh_frame_hdr表

c - 赋值 <指向常量数组的指针> = <指向数组的指针> : incompatible pointers

c - 如何消除 Linux 中 DDA 行算法中的以下错误?

visual-studio-2008-sp1 - 强制 VS2008 发出类似 "warning: comparison between signed and unsigned integer expressions"的 GCC 警告