const char * 与 const char ** 函数参数
const char * vs. const char ** function argument
我已经阅读了 C FAQ on const,但我仍然感到困惑。
我的印象是(显然是错误的)函数声明中的 const 本质上是一个承诺,即该函数不会修改您标记为 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 **'
f2( v1 ); /* compiler warning - why? */
compiler warning - why?
因为char**
和const char**
不一样。他们的待遇不同。
char** v1 // pointer to pointer to char
在这里您可以更改 **v1
的值。
而
const char** v2 //pointer to pointer to constant char
在这里您不能更改 **v2
的值,如果您尝试编译器会发出错误。
标准禁止这样做,因为那样会违反对象的常量性。考虑:
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_pptr
和 ch_ptr
产生相同的值(地址),但它们的类型不同(const char*
和 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;
}
我已经阅读了 C FAQ on const,但我仍然感到困惑。
我的印象是(显然是错误的)函数声明中的 const 本质上是一个承诺,即该函数不会修改您标记为 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 **'
f2( v1 ); /* compiler warning - why? */
compiler warning - why?
因为char**
和const char**
不一样。他们的待遇不同。
char** v1 // pointer to pointer to char
在这里您可以更改 **v1
的值。
而
const char** v2 //pointer to pointer to constant char
在这里您不能更改 **v2
的值,如果您尝试编译器会发出错误。
标准禁止这样做,因为那样会违反对象的常量性。考虑:
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_pptr
和 ch_ptr
产生相同的值(地址),但它们的类型不同(const char*
和 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;
}