c - 当我使用 const 作为指针时,我收到不兼容的指针类型警告
问题描述
编写以下代码时:
#include <general.dep>
typedef struct {
} obj;
int f1(obj **o) {
return 0;
}
int f2(obj *const *o) {
return 0;
}
int f3(const obj **o) {
return 0;
}
int f4(const obj *const *o) {
return 0;
}
int main() {
obj **o;
f1(o);
f2(o);
f3(o);
f4(o);
return 0;
}
我收到以下警告消息:
gcc t1.c -I/home/hamidi/code/lib/general/inc -fmax-errors=1 -lgeneral -llzma -pthread -o t1
t1.c: In function ‘main’:
t1.c:26:6: warning: passing argument 1 of ‘f3’ from incompatible pointer type [-Wincompatible-pointer-types]
26 | f3(o);
| ^
| |
| obj ** {aka struct <anonymous> **}
t1.c:14:20: note: expected ‘const obj **’ {aka ‘const struct <anonymous> **’} but argument is of type ‘obj **’ {aka ‘struct <anonymous> **’}
14 | int f3(const obj **o) {
| ~~~~~~~~~~~~^
t1.c:27:6: warning: passing argument 1 of ‘f4’ from incompatible pointer type [-Wincompatible-pointer-types]
27 | f4(o);
| ^
| |
| obj ** {aka struct <anonymous> **}
t1.c:18:26: note: expected ‘const obj * const*’ {aka ‘const struct <anonymous> * const*’} but argument is of type ‘obj **’ {aka ‘struct <anonymous> **’}
18 | int f4(const obj *const *o) {
| ~~~~~~~~~~~~~~~~~~^
如何解决这些警告问题?
更新
我标记了发出以下警告的函数:
void f0(obj **ppo) {}
void f1(const obj **ppo) {} //
void f2(obj const **ppo) {} //
void f3(obj *const *ppo) {}
void f4(obj **const ppo) {}
void f5(const obj const **ppo) {} //
void f6(const obj *const *ppo) {} //
void f7(const obj **const ppo) {} //
void f8(obj const *const *ppo) {} //
void f9(obj const **const ppo) {} //
void fa(obj *const *const ppo) {}
void fb(const obj const *const *ppo) {} //
void fc(const obj const **const ppo) {} //
void fd(const obj *const *const ppo) {} //
void fe(obj const *const *const ppo) {} //
void ff(const obj const *const *const ppo) {} //
我不确定哪些是等价的。似乎 f2 和 f3 不同,因为 f2 发出警告而 f3 没有。那么,我们可以说obj const *
与 不同obj *const
吗?
更新 2
obj 的 const 可以放在它之前或之后,但对于指针,它应该放在它们之后。所以,让我们把两者都放在 const 之后。现在我的问题是在以下代码中:
void f(int const* const* ppi) {
//**ppi = **ppi;
//*ppi = *ppi;
ppi = ppi;
}
void g(int const* pi) {
//*pi = *pi;
pi = pi;
}
int main() {
int i, *pi = &i, **ppi = π
f(ppi);
g(pi);
return 0;
}
我调用了两个函数,f & g。两个函数原型都表明参数的内容没有改变。g 不会改变指针的内容, f 不会改变指针的内容和指针内容指向的内容。
现在我的问题是,为什么编译器仅在调用 f 而不是 g 时才发出此警告?!如果 f 要说我不会更改指针的内容和它指向的内容,那么它的原型应该是什么?
warning: passing argument 1 of ‘f’ from incompatible pointer type [-Wincompatible-pointer-types]
16 | f(ppi);
| ^~~
| |
| int **
t2.c:3:26: note: expected ‘const int * const*’ but argument is of type ‘int **’
3 | void f(int const* const* ppi) {
| ~~~~~~~~~~~~~~~~~~^~~
解决方案
更新:此答案已更新以修复评论中讨论的错误
与指针一起使用时的工作方式const
有点微妙。
const obj*
andobj const*
表示指针指向 const obj 类型,而obj* const
表示指针是 const 并指向非 const obj 类型。
使用这个逻辑const obj**
等价于obj const**
which 是一个非常量指针,它指向一个指向一个 const obj 的非常量指针,而obj* const*
一个非常量指针指向一个指向一个非常量 obj 的 const 指针。Andobj** const
是一个指向非 const 指针的 const 指针,该指针指向一个非 const obj。
C++ 可以将非常量类型隐式转换为 const 类型。f2(o)
您可以在隐式转换obj*
为的调用中看到这一点obj* const
。
另一方面,C++ 在隐式转换多级指针时必须小心。如果 C++ 允许obj**
隐式转换为const obj**
以下代码,则允许:
const int x = 0; //x should never be modified
int* xPtr;
const int** xPtrPtr = &xPtr; //would be legal if C++ allowed int** -> const int** conversion
*xPtrPtr = &x;
*xPtr = 1; //This changes the value of x!
出于这个原因,GCC 在调用时会发出错误,f3(o)
因为它隐式地将 a 转换obj**
为const obj**
.
您可以在此处阅读多级指针转换的完整要求
我不知道你需要你的代码做什么,但如果你要修改底层obj
或obj*
inf3
你应该将它的参数更改为obj** const
. 如果您不想修改底层obj
但修改obj*
您应该改为使用obj const**
作为参数。如果你不想修改或者obj
你obj*
应该使用obj const* const*
推荐阅读
- angular - 错误:无法匹配任何路由。URL 段:'access_token'
- arrays - 我正在使用 NetBean GUI,在我从数组中添加或删除一个项目并输出它之后,它将不再接受输入
- c# - 在 ASP.NET Core MVC 中使用自定义验证调试模型
- javascript - 尽管将它放在“文档就绪”中,但为什么我在加载页面时会看到 jQuery 'append' 发生?
- asp.net-core - 如何显示自定义 404 页面而不是浏览器的默认页面?当我使用我的 Razor Pages 应用程序时
- django - django - 显示单个用户的对象
- python - Firebase .get 函数:get() 接受 2 个位置参数,但给出了 3 个
- mysql - MySQL NodeJS 的 createConnection 与 createPool
- api - 如何在空手道中将“数字”转换为数字
- oauth-2.0 - 为什么检索访问令牌是 OAuth2 中带有额外 HTTP 请求的单独步骤?