const指针与typedef的交互以及c中的函数声明
Posted
技术标签:
【中文标题】const指针与typedef的交互以及c中的函数声明【英文标题】:Interaction between const pointer and typedef and function declaration in c 【发布时间】:2022-01-19 01:01:20 【问题描述】:我这里有这段代码:
#include <stdio.h>
int add(const int* x, const int* y);
int main()
int x = 4;
int y = 3;
printf("%d", add(&x, &y));
return 0;
int add(int* x, int* y)
return *x + *y;
当我编译时它给了我一个错误:添加冲突的类型 我知道我必须将 const 放入函数定义的参数中。 但是,如果我像这样在代码中添加 typedef:
#include <stdio.h>
typedef int* int_ptr;
int add(const int_ptr x, const int_ptr y);
int main()
int x = 4;
int y = 3;
printf("%d", add(&x, &y));
return 0;
int add(int_ptr x, int_ptr y)
return *x + *y;
它编译并给了我输出:7 为什么会这样?
【问题讨论】:
你知道const int_ptr
等价于int * const
而不是const int *
?
哦,我不知道,那我怎么能从 typedef 定义中得到 const int *
你不能。 typedefs
不要那样工作。
Typedef 不是宏,它们不是文字替换。
为什么要让函数声明与定义不同?
【参考方案1】:
在const int* x
中,const int
是说明符,*x
是声明符。 (这种分隔是由 C 的形式文法指定的,这也是为什么将声明写成 int* x
会歪曲文法的原因。)这个声明说 *x
是 const int
,意思是 x
是指向 @987654328 的指针@。
在typedef int* int_ptr
中,typedef int
是说明符,*int_ptr
是声明符。声明说*int_ptr
是一个int
,typedef
是一个特殊的说明符,它修改它以便int_ptr
被声明为一个类型,而不是一个对象(变量)。
在const int_ptr x
中,const int_ptr
是说明符,x
是声明。所以这个声明说x
是const int_ptr
。
这里const
正在修改int_ptr
; const int_ptr x
表示 x
是一个指向 int
的 const
指针。在const int *x
中,const
修改了int
,所以它说*x
是一个指向const int
的指针,意思是x
是一个指向const int
的指针。
在大多数情况下,当使用参数类型列表声明函数时,函数的每个声明中的参数必须具有兼容的类型。但有一个例外:C 2018 6.7.6.3 15 说:
…(在确定类型兼容性和复合类型时,…用限定类型声明的每个参数都被视为具有其声明类型的非限定版本。)
这表示,在确定 int add(const int_ptr x, const int_ptr y)
是否与 int add(int_ptr x, int_ptr y)
兼容时,const
限定符将被忽略。那么参数类型是一样的,所以函数声明是兼容的。
在int add(const int *x, const int *y)
、x
和y
中不符合const
。它们指向const int
,但它们本身不是const
。也就是说,x
的指针可以更改(不是const
)。它指向const
的事实并不能使它成为const
。所以关于忽略函数参数中的限定符的规则在这里不适用; x
和 y
上没有限定符。所以int add(const int *x, const int *y)
和int add(int *x, int *y)
没有兼容的参数类型。
关于忽略参数类型中的限定符的这条规则的原因是限定符只影响对象,而不影响值。如果我们有一个对象x
即const
,则不应更改(通过该类型)。但是,如果我们从x
得到int
的值3 并在表达式中使用它,那么说3 是const
是没有意义的。它只是表达式中使用的值;没有分配给它的内存,我们可以在其中存储一个将 3 更改为 4 的新值。一旦从 const int
检索到对象的值,它就只是一个 int
。
类似地,如果我们有一个volatile int x
,volatile
意味着编译器必须在每次在表达式中使用它时获取x
的值,因为volatile
意味着可能会改变@ 的内存987654382@ 编译器不知道的方式。但是,一旦我们从内存中获得了x
的值,它就只是一个值。我们已经完成了“你必须从内存中获取它”部分,所以volatile
不再起作用。
由于函数参数总是按值传递,所以限定符与调用者无关。当使用void foo(const int x)
声明函数时,const
在函数内部具有含义:如果函数内部的任何内容尝试使用其const
限定类型修改x
,编译器必须发出诊断。但是调用者并不关心:调用者只传递一个值。函数启动时,会为自己创建一个本地的x
,而那个x
就是const
,但是对调用者没有影响。所以void foo(int x)
和void foo(const int x)
是兼容的函数声明。
【讨论】:
以上是关于const指针与typedef的交互以及c中的函数声明的主要内容,如果未能解决你的问题,请参考以下文章