C语言常量与指针
2014-06-24 17:47
225 查看
C语言功能强大而丰富,还表现在const与指针的结合使用上,对不同的问题,它提供不同的保护,特别有用的是指向常量的指针
本文地址:http://www.cnblogs.com/archimedes/p/c-const-point.html,转载请注明源地址。
下面的代码会打印这些变量的地址和值:
不能解引指向常量的指针并改变指针所引用的值,但是指针的值不是常量,可以改变指针,指针可以改为引用另一个整数常量或普通整数
把pci声明为指向整数常量的指针意味着:
pci可以被修改为指向不同的整数常量
pci可以被修改为指向不同的非整数常量
可以解引pci以读取数据
不能解引pci从而修改它指向的数据
注意:数据类型和const的顺序无关紧要,可以互换
const int *pci = int const *pci
如果将cpi初始化为指向常量limit将产生错误,因为cpi指向的数据可以修改,但是常量是不能被修改的
不一定只能将常量的地址赋给cpci,如下:
声明此类指针的时候必须进行初始化
下表总结所讨论的四种指针:
如果我们试图修改,我们将得到一个gcc error
error: assignment of read-only location ‘*ptr’
如果将值赋值给一个非结构体常量,我们将得到gcc的警告
warning: assignment discards qualifiers from pointer target type
如果使用类型转换将可以成功运行
结构体常量指针作为参数
常量指针
将一个指针指定为常量的,const关键字放在"*"的后面,就像上面的do_something()原型可以改写为下面的形式,所有的都不可以修改,ptr变量通过调用传递参数初始化,以后就不能修改
常量初始化延伸
一个结构体常量可以像下面这样初始化:
一个指向结构体常量的指针可以像下面这样初始化:
返回常量指针
传递指向常量指针的指针
一个常见传递二重指针的原因就是需要修改指针值,看下面的例子:
再看下面的代码,在location前面加上const
解释如下:
1、结构体是常量的,内容不能修改
2、指向该结构体的指针,通过location指向,*location不是常量,可以修改
3、变量location是常量的,意味着不能被修改
还可以添加一个const:
error: assignment of read-only location ‘*location’ (由于*location也是常量,所以会得到gcc error)
下面的代码不是操作结构体的内容,也不是指向结构体的指针,而是允许函数通过传递的参数操作它自身的局部变量
解释如下:
1、结构体是常量的,内容不能修改
2、指向该结构体的指针,通过location指向,*location也是常量,不可以修改
3、变量location是非常量,意味着可以被修改
4、局部变量ptr_a是常量,不可以被修改
4、局部变量ptr_a不是常量,可以被修改
《C和指针》
本文地址:http://www.cnblogs.com/archimedes/p/c-const-point.html,转载请注明源地址。
指向常量的指针
可以将指针指向常量,这就意味着不能通过指针修改它所引用的值int num = 5; const int limit = 500; int *pi; const int *pci; pi = # //指向整数 pci = &limit; //指向整数常量
下面的代码会打印这些变量的地址和值:
#include <stdio.h>
int main(void)
{
int num = 5; const int limit = 500; int *pi; const int *pci; pi = # //指向整数 pci = &limit; //指向整数常量
printf(" num - Address:%p value:%d\n", &num, num);
printf("limit - Address:%p value:%d\n", &limit, limit);
printf(" pi - Address:%p value:%p\n", &pi, pi);
printf(" pci - Address:%p value:%p\n", &pci, pci);
return 0;
}
不能解引指向常量的指针并改变指针所引用的值,但是指针的值不是常量,可以改变指针,指针可以改为引用另一个整数常量或普通整数
把pci声明为指向整数常量的指针意味着:
pci可以被修改为指向不同的整数常量
pci可以被修改为指向不同的非整数常量
可以解引pci以读取数据
不能解引pci从而修改它指向的数据
注意:数据类型和const的顺序无关紧要,可以互换
const int *pci = int const *pci
指向非常量的常量指针
指针不可变,但是它指向的数据可变int num; int *const cpi = #
如果将cpi初始化为指向常量limit将产生错误,因为cpi指向的数据可以修改,但是常量是不能被修改的
const int limit = 500; int * const cpi = &limit;
指向常量的常量指针
这种类型的指针很少使用,这种指针不能修改,它指向的数据也不能通过它来修改,下面是一个例子:const int * const cpci = &limit;
不一定只能将常量的地址赋给cpci,如下:
int num; const int * const cpci = #
声明此类指针的时候必须进行初始化
指向“指向常量的常量指针”的指针
#include <stdio.h> int main(void) { const int limit = 500; const int * const cpci = &limit; const int * const * pcpci = &cpci; printf("%d\n", *cpci); printf("%d\n", **pcpci); return 0; }
下表总结所讨论的四种指针:
指针类型 | 指针是否可修改 | 指向指针的数据是否可修改 |
指向非常量的指针 | 是 | 是 |
指向常量的指针 | 是 | 否 |
指向非常量的常量指针 | 否 | 是 |
指向常量的常量指针 | 否 | 否 |
举例说明
下面的例子中,function函数返回一个指向结构体常量的指针,意味着结构体中的值是只读的,限定符很有用,因为它告诉我们一些不能进行的操作#include<stdio.h> #include<stdlib.h> struct a { int x; }; const struct a * function(void) { struct a *ptr; if((ptr = (struct a *)malloc(sizeof(struct a))) == NULL) exit(1); ptr->x = 0; return ptr; } int main(void) { int y; const struct a *ptr; ptr = function(); y = ptr->x; return 0; }
如果我们试图修改,我们将得到一个gcc error
int main(void) { int y; const struct a *ptr; ptr = function(); ptr->x = 1; return 0; }
error: assignment of read-only location ‘*ptr’
如果将值赋值给一个非结构体常量,我们将得到gcc的警告
int main(void) { int y; struct a *ptr; ptr = function(); ptr->x = 1; return 0; }
warning: assignment discards qualifiers from pointer target type
如果使用类型转换将可以成功运行
int main(void) { struct a *ptr; ptr = (struct a *) function(); ptr->x = 1; return 0; }
结构体常量指针作为参数
#include<stdio.h> #include<stdlib.h> struct a { int x; }; struct b { const struct a *nested_ptr; }; const struct a * function(void) { struct a *ptr; if((ptr = (struct a *) malloc(sizeof(struct a))) == NULL){ exit(1); } ptr->x = 0; return ptr; } void do_something(const struct b *ptr) { const struct a *x = ptr->nested_ptr; } int main(void) { struct b b_obj; b_obj.nested_ptr = function(); do_something(&b_obj); return 0; }
常量指针
将一个指针指定为常量的,const关键字放在"*"的后面,就像上面的do_something()原型可以改写为下面的形式,所有的都不可以修改,ptr变量通过调用传递参数初始化,以后就不能修改
void do_something(const struct b * const ptr);
常量初始化延伸
一个结构体常量可以像下面这样初始化:
int main(void) { const struct a obj = [ 5 ]; return obj.x; }
一个指向结构体常量的指针可以像下面这样初始化:
int main(void) { const struct a obj = [ 5 ]; const struct a *ptr_a = &obj; const struct a *ptr_b = function(); return ptr_a->x; }
返回常量指针
const struct a * const function(void);
传递指向常量指针的指针
一个常见传递二重指针的原因就是需要修改指针值,看下面的例子:
void fill_in(const struct a **location) { *location = function(); } int main(void) { const struct a *ptr; fill_in(&ptr); return 0; }
再看下面的代码,在location前面加上const
void fill_in(const struct a ** const location) { *location = function(); }
解释如下:
1、结构体是常量的,内容不能修改
2、指向该结构体的指针,通过location指向,*location不是常量,可以修改
3、变量location是常量的,意味着不能被修改
还可以添加一个const:
void fill_in(const struct a * const * const location) { *location = function(); }
error: assignment of read-only location ‘*location’ (由于*location也是常量,所以会得到gcc error)
下面的代码不是操作结构体的内容,也不是指向结构体的指针,而是允许函数通过传递的参数操作它自身的局部变量
void make_use_of(const struct a * const *location) { const struct a * const ptr_a = *location; const struct a *ptr_b = *location; ptr_b = NULL; location = NULL; }
解释如下:
1、结构体是常量的,内容不能修改
2、指向该结构体的指针,通过location指向,*location也是常量,不可以修改
3、变量location是非常量,意味着可以被修改
4、局部变量ptr_a是常量,不可以被修改
4、局部变量ptr_a不是常量,可以被修改
参考资料
维基百科《C和指针》
相关文章推荐
- C语言中指向常量的指针和指针常量
- C语言:指向常量的指针 和 指针常量
- C语言中的const用法以及常量指针与指针常量(有口诀!)
- C语言-常量指针与指针常量
- 一篇文章搞懂c语言常量与指针的几个排列组合
- 关于C语言指针常量
- C语言中的常量指针与指针常量
- C语言中的常量指针和指针常量
- [C++][转] C语言:常量指针,指针常量,左移,右移 .
- C语言的指针 指针常量 只读 多维数组的指针
- c语言 数组名是常量指针
- C语言中的常量指针与指针常量
- C语言: 空指针和空指针常量
- C语言拾遗:常量指针与指针常量(const int *ptr, int const *ptr, int * const ptr, const int * const ptr区别)
- C语言——常量指针、指针常量以及指向常量的指针常量三者区别详解
- C语言中常量指针与指针常量区别浅析
- 浅谈C语言中变量、常量、数组、字符串、指针的地址
- c语言的指针、数组和常量修饰符const
- C语言常量与指针
- C语言学习笔记 (001) - 常量指针与指针常量的区别(转帖)