C语言 不兼容的常量指针

e4eetjau  于 2023-10-16  发布在  其他
关注(0)|答案(3)|浏览(73)

传递一个非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 = &pi;

  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

有什么启示吗?

xfyts7mz

xfyts7mz1#

原因在C标准中给出。下面的代码来自C 2018 6.5.16.1 6。评论是我的。
鉴于这些声明:

const char **cpp;
char *p;
const char c = ’A’;

假设我们允许(通过函数调用或直接赋值)将char **赋值给const char **,如下所示:

cpp = &p;

然后,由于*cppconst char *,我们可以给它赋值const char *,如下所示:

*cpp = &c;

由于cpp指向p,因此*cpp = &cp更改为指向c*p名义上是char,我们可以给char赋值:

*p = 0;

这改变了c,它是用const定义的。所以这是不允许的。赋值cpp = &p被禁止,因此不会发生这种情况。

8oomwypt

8oomwypt2#

我希望它能让你更清楚:

#include <stdio.h>

int foo(const int *i)
{
  return *i;
}

int bar(const int **i)
{
  return **i;
}

int main(void)
{
  int i = 3;
  const int *pi = &i; 
  const int **ppi = &pi;

  printf("foo: %i\n", foo(pi));
  printf("bar: %i\n", bar(ppi));

  return 0;
}
mo49yndu

mo49yndu3#

const指针通常声明指向的值不可修改,因此如果您试图修改指向的数据,编译器将引发错误。但是,如果你通过将const指针赋给非const变量(如在参数传递或赋值语句中)来别名const指针,那么别名指针将不再受到编译器的保护,它将允许你通过新的非const指针值修改指针数据。
有时,这正是我们想要的,但在这种情况下,您可以通过在参数传递代码或变量赋值中转换为非const指针类型来显式地声明它,这实际上将声明您的真实的意图。由于允许这种赋值是非常危险的,编译器默认会发出一个警告(警告可以像前面所说的那样避免,或者只是用编译选项禁用警告)。

相关问题