C# · 2月 14, 2022

C语言指针常量和指向常量的指针

指针常量本质是一个常量,而用指针修饰它,那么说明这个常量的值应该是一个指针。指针常量 的值是指针,这个值因为是常量,所以不能被赋值。因为指针常量是一个常量,在声明的时候一定要给它赋初值。一旦赋值,以后这个常量再也不能指向别的地址。下面的例子展示了指针常量不同于指向常量的指针:int var; // 一个int类型的对象int *const c_ptr = &var; // 一个int类型指针常量*c_ptr = 123; // 合法:我们可以修改它所引用的对象++c_ptr; // 错误:我们不能修改指针
当一个指针指向具有 const 限定的对象,称为指向常量的指针,可以修改该指针的值。然而,只能使用这样的指针来读取所指向的对象,但不能修改所指向的对象。因此,指向常量的指针常常被称为只读指针(read-only pointer)。所引用对象本身可以是常量,也可以不是常量。例子如下:int var; //一个int类型的对象const int c_var = 100,// 一个int类型的常量对象 *ptr_to_const; // 一个指向常量的指针:指针本身不是常量!ptr_to_const = &c_var; // 合法:使得ptr_to_const指向c_varvar = 2 * *ptr_to_const; // 合法:等效于var = 2 * c_varptr_to_const = &var; // 合法:使得ptr_to_const指向varif ( c_var < *ptr_to_const ) // 合法:“只读”方式获取 *ptr_to_const = 77; // 错误:我们不能使用ptr_to_const修改var, // 尽管var不是常量
类型修饰符和类型限定符可以以任何顺序排列。因此,下面的写法是合法的:int const c_var = 100,*ptr_to_const;
赋值表达式 ptr_to_const=&var 必需采用隐式转换:int 指针值 &var 会自动地转换成左操作数的类型,也就是指向 const int 的指针。对于与之类似的类型操作数的运算符,编译器会隐式地将指向某一类型T的指针,转换为具有更多限定符的类型 T 的指针。

如果想将一个指针转换为有较少限定符的类型,必须使用显式的类型转换。下面的程序代码片段使用前面例子所声明的变量:int *ptr = &var; // 一个指向var的int指针*ptr = 77; // 合法:ptr 不是一个只读指针ptr_to_const = ptr; // 合法:隐式地将ptr从指向int的指针 // 转换为指向int常量的指针*ptr_to_const = 77; // 错误:不能通过一个只读指针修改一个变量ptr = &c_var; // 错误:不能隐式地将指向int常量的指针转换 // 为指向int 的指针ptr = (int *)&c_var; // 合法:显式的指针类型转换总是可行的*ptr = 200; // 尝试修改c_var:可能会造成运行错误
如果编译器将常量对象 c_var 放置在内存中的只读区域,那么最后一条语句将会引发运行错误。

也可以声明指向常量的常量指针,如下面函数原型的参数声明:void func( const int * const c_ptr_to_const );
该函数的参数是只读指针,当该函数被调用时该只读指针参数会被初始化,并且在函数执行过程中保持该值不变。