传递一个非const指针到一个需要const指针的函数通常不会引起警告(这是有道理的,这个函数承诺比调用者期望的“更好”),但是一个非const指针到一个需要const指针到指针的函数确实会引起警告(在gcc -Wall
,11.4中),我很难想象为什么
#include <stdio.h>
int foo(const int *i)
{
return *i;
}
int bar(const int **i)
{
return **i;
}
int main(void)
{
int i = 3, *pi = &i, **ppi = π
printf("foo: %i\n", foo(pi));
printf("bar: %i\n", bar(ppi));
return 0;
}
给
$ gcc -Wall -o const const.c
const.c: In function ‘main’:
const.c:18:27: warning: passing argument 1 of ‘bar’ from incompatible pointer type [-Wincompatible-pointer-types]
18 | printf("bar: %i\n", bar(ppi));
| ^~~
| |
| int **
const.c:8:21: note: expected ‘const int **’ but argument is of type ‘int **’
8 | int bar(const int **i)
| ~~~~~~~~~~~~^
$ ./const
foo: 3
bar: 3
有什么启示吗?
3条答案
按热度按时间xfyts7mz1#
原因在C标准中给出。下面的代码来自C 2018 6.5.16.1 6。评论是我的。
鉴于这些声明:
假设我们允许(通过函数调用或直接赋值)将
char **
赋值给const char **
,如下所示:然后,由于
*cpp
是const char *
,我们可以给它赋值const char *
,如下所示:由于
cpp
指向p
,因此*cpp = &c
将p
更改为指向c
。*p
名义上是char
,我们可以给char
赋值:这改变了
c
,它是用const
定义的。所以这是不允许的。赋值cpp = &p
被禁止,因此不会发生这种情况。8oomwypt2#
我希望它能让你更清楚:
mo49yndu3#
const
指针通常声明指向的值不可修改,因此如果您试图修改指向的数据,编译器将引发错误。但是,如果你通过将const
指针赋给非const
变量(如在参数传递或赋值语句中)来别名const
指针,那么别名指针将不再受到编译器的保护,它将允许你通过新的非const
指针值修改指针数据。有时,这正是我们想要的,但在这种情况下,您可以通过在参数传递代码或变量赋值中转换为非
const
指针类型来显式地声明它,这实际上将声明您的真实的意图。由于允许这种赋值是非常危险的,编译器默认会发出一个警告(警告可以像前面所说的那样避免,或者只是用编译选项禁用警告)。