C 指针
2016-11-04 12:24
127 查看
1 C 指针
指针的内容是其所指向的地址,间接访问操作符访问的是指针指向的地址,作为左值时,就是那个位置,作为右值时,就是那个位置的值。&, 取地址运算符, 引用运算符
*, 间接访问运算符, 解引用运算符
不能使用变量指针指向常量的地址, 因为既然通过变量名不能改变变量值, 而通过指针变量也应该是不可以的, 可以通过强制类型转换(const_cast)突破此限制 primer p222
只有一层间接关系时, 使用指向常量的指针指向变量才是安全的 p222
两层间接关系时, 使用指针常量指向指针变量, 则指针常量间接访问到的是一个指针变量, 而指针变量可以修改其指向的值
1 指向整型变量的指针
指向整型变量的指针类型的变量,没啥好解释的。int *pointer;
2 指向整型常量的指针
指针的内容,即指向的地址可变,即该指针可以指向另一个整型常量,但指向的这些整型值都是不变的const 限定符修饰的是*p, 即指向的值, 是间接访问到的那个变量的值不能通过该指针修改, 但不影响该变量本身是变量或常量, 通过变量名修改其值
const int *p = NULL; int const *p = NULL;
3 指向整型变量的指针常量(pointer constant)
指针的内容,即指向的地址是字面值或常量,是不变的。但指向的整型值可变。const 限定符修饰的是 p 本身, 即指针本身不能变
使用字面值形式的指针常量时, 一般只会用于已知的设备地址,否则程序中一般无法了解一个变量的具体地址。使用时应使用强制类型转换,将整数转换为指针类型。
数组是矢量类型的数据,数组名本质上是一个指针常量,因此数组元素可以利用指针运算进行访问。
int *const pointer; // 常量指针 (int *) 0xff2044ec; // 设备I/O地址 (int *) 0x0; // NULL 指针 int array[]; // 数组
4 指向整型常量的指针常量
指针内容不变,指针指向的内容也不变。int const *const pointer;
5 指向数组的指针
第一个声明中,二维数组名是一个指向数组的指针常量。第二个声明中,操作数 pointer 先进行聚组中的间接访问,说明它是一个指针,再进行下标引用,说明指向的是一个整型数组。
第三行对指针进行初始化。
注意区分指针数组和指向数组的指针,前者是数组元素是指针的数组, 后者是指向数组的指针。
int matrix[3][10]; int (*pointer)[10]; (*pointer)[10] = matrix;
6 指向结构的指针
结构和数组的重大区别在于,前者是一个标量,也就是需要通过名字来访问。结构不能够像数组那样进行指针运算和按地址访问。当结构作为函数参数时,进行的是传值调用,如果结构很庞大,会造成很大的开销。因此应该用指向结构的指针作为函数参数。
struct tag structname; struct tag *pointer = &structname;
7 指向函数的指针
函数名称本质上跟数组名类似,也是一个指针。指向函数的指针有两个常见用途,一是转换表(jump table),二是回调函数(callback function)。
第一个声明中,首先进行间接访问,表示 f 是一个指针,再进行函数调用操作,表示 f 这个指针指向的是一个函数,这个函数返回整型值。
第二个声明中,需要一步一步的分析,f 是一个数组,数组元素是指针,指针指向的是函数,函数的返回类型是整型。
第三个声明中,与前者的唯一区别是,函数的返回类型是指向整型的指针。
int (*f)(); int (*f[])(); int *(*f[])();
8 指向指针的指针
如果 ppi 是静态变量,那么在声明后,ppi 的值为0。ppi被初始化后,才可以对 ppi 进行间接访问。
*pi 指向变量 i,其内容是变量 i 的值。
*ppi 指向 pi,其内容是变量 i 的地址。
**ppi 内容是变量 i 的值。
int i; int *pi; int **ppi; pi = &i; ppi = π
2 C 指针表达式
char c = ‘a’; char *p = &c;
表达式 | 右值 | 左值 | 对p的副作用 | 对c的副作用 |
---|---|---|---|---|
p | p的内容(c的地址) | p的地址 | ||
&p | p的地址 | |||
*p | c的内容 | c的地址 | ||
*p + 1 | c的内容+1 | |||
*(p + 1) | c后面位置的内容 | c后面位置的地址 | ||
++p | c后面位置的地址 | c后面位置的地址 | ||
p++ | c的地址 | c后面位置的地址 | ||
*++p | c后面位置的内容 | c后面位置的地址 | c后面位置的地址 | |
*p++ | c的内容 | c的地址 | c后面位置的地址 | |
++*p | c的内容+1 | c的内容+1 | ||
(*p)++ | c的内容 | c的内容+1 | ||
++*++p | c后面位置的内容+1 | c后面位置的地址 | c后面位置的内容+1 | |
++*p++ | c的内容+1 | c后面位置的地址 | c的内容+1 |
3 参考
Kenneth A. Reek 著《C 和指针》相关文章推荐
- 怎样将成员函数指针强制转换成void*指针?
- C++Primer学习笔记第四章(4/18) 数组和指针
- [转载]强制类型转换 类型的本质 指针的本质 函数指针
- c++ 指针与引用的区别
- 作业5 指针应用1
- 指针与数组
- C语言中两个指针之间的运算
- 字符数组与字符指针
- 数组与指针
- C语言指针系列
- C++之指针
- 指针、引用、数组和字符串,你真的全弄清楚了吗?
- 数组、指针与字符串
- 强制类型转换为基类指针与赋值兼容规则下转换为基类指针的比较
- NSValue包装对象指针,CGRect结构体等
- 20131111实验 10 指针2
- 指针和引用中一些要注意的问题
- 通过引用计数解决野指针的问题(C&C++)
- 关于hive数据库查询操作出现的空指针问题
- C语言——输出与指针(1)