前言
我们都知道const可以修饰数据类型,例如:
int *const p表示定义了一个常量指针;
const int* p表示定义了一个指向常量的指针;
关于常量指针以及指向常量的指针的区别可以参考笔者的另一篇文章C语言-常量指针与指向常量的指针.
我们也知道可以使用typedef关键字来定义数据类型的别名,例如:
typedef int MyInt
typedef struct student student_t
typedef void (*my_func)(void);
但是当我们使用typedef关键字定义指针类型的别名时,在前方加入修饰符const可能会和我们实际想的情况不一样.
#include <stdio.h>
void func(const int* cfg) {
return;
}
int main(void) {
const int data = 10;
func(&data);
return 0;
}
在这个例子中,func的参数为const int*的指针类型,然后我们定义了一个const int类型的data,将data的地址作为参数传递.
然后我们编译,没有报错.
说明const修饰的数据取地址转为指针时,默认转成了一个指向常量的指针.
那么我们稍微修改一下代码,使用typedef定义一个别名来指代int*:
#include <stdio.h>
typedef int* int_ptr_t;
/* const int_ptr_t 被转换成了 int *const, 变成了一个指针常量 */
void func(const int_ptr_t cfg) {
return;
}
int main(void) {
const int data = 10;
/* &data 被转换成了 const int*, 是一个指向常量的指针 */
func(&data);
return 0;
}
在上述代码中,我们使用typedef定义了一个别名int_ptr_t,用来指代int*这个指针类型.然后函数的参数为const int_ptr_t.
然后我们编译一下,出现了警告:
╰─❯ gcc main.c
main.c: In function ‘main’:
main.c:14:10: warning: passing argument 1 of ‘func’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
14 | func(&data);
| ^~~~~
main.c:6:27: note: expected ‘int_ptr_t’ {aka ‘int * const’} but argument is of type ‘const int *’
6 | void func(const int_ptr_t cfg) {
这个警告的类型是[-Wdiscarded-qualifiers]丢失的限定符,说我们func函数放弃指针目标类型中的const限定符, 参数预期要的是int_ptr_t {aka ‘int * const’}这个类型,但是实际传入了‘const int *’.
实际传入的类型确实是const int*,这个也是我们期望的类型,但是函数的参数怎么变成了int * const?
这是因为我们typedef关键字定义别名并不是像define一样进行替换.
我们的int_ptr_t指代的是int*指针类型,const int_ptr_t修饰的应该是这个指针,所以转变成了常量指针int *const.