参考书籍《深入理解c指针》
原书作者:Richard Reese 华盛顿州塔尔顿州立大学副教授
如果想在C/C++道路上走的更远,那么必须非常熟悉指针
1、关于指针大小的谣言,指针到底多大?
指针占据内存大小,
64位平台下是8
32位平台下是4
一、指针和内存
1、为什么要精通指针
支持动态分配、快速,高效
2、声明指针
int *pi;
3、如何阅读声明
倒过来读,例如指向常量的指针
const int *pci;//指向常量的指针变量
4、地址操作符
地址操作符&会返回操作数的地址,利用这个操作符来初始化pi指针,如
int num = 0;
pi = #
5、打印指针的值
%x 将值显示为十六进制数
%p 十六进制数大写
6、接引操作符解引指针
解引操作符 *
解引操作符的结果叫做左值,也就是赋值操作符左边的操作数,所有的左值都必须可修改
int num = 5;
int *pi = #
*p = 200;
printf("%d\n",num); // 200
7、指向函数的指针
void (*foo)()
8、null概念
(一)、用不用NULL
<1>null概念,
指针包含一个特殊的值,不指向任何区域
<2>null指针常量
<3>NULL宏 ,
强制类型转换为Void指针的整数常量0,在很多库中定义如下
#define NULL ((void *)0)
<4>ASCALL字符串NULL,
全0的字节.
<5>null 字符串,
以0值为结尾的空字符串,不包含任何字符
<6>null语句
只有一个分号的语句
注意
空指针和未初始化的指针不一样,未初始化的指针可能包含任何值
可以为指针赋值为0,但是不能赋值为别的值
任何时候都不应该对指针进行接引,因为它并不包含合法地址,否则会导致程序终止
<7>0的含义随着上下文的变化而变化
int num;
int *pi = 0;// 指针NULL
pi = #
*p = 0; // 整数0
(二)、void 指针
void指针是通用指针,用来存放任何数据类型的引用
void *pv;
两个有意思的特点
<1>void指针和char指针形式相同,内存对齐方式相同
<2>void指针和别的指针永远不会相等,但是两个赋值为NULL的指针是相等的
(三)、全局和静态指针
指针被声明为全局或静态,就会在程序启动时被初始化为NULL;
二、指针长度和类型
1、内存模型:
模型取决于操作系统和编译器,一个操作系统可能支持多种模型,这是由编译器选项来控制的
2、指针相关的预定义模型
使用指针时候经常用到的地中预定义模型
size_t用于安全地表示长度
ptrdiff_t 用于处理指针算术运算
intptr_t和uintptr_t 用于存储指针地址
<1> size_t
在stdio.h和stdlib.h中,定义如下
#ifdef _SIZE_T
#define _SIZE_T
typedef unsigned in size_t
#endif
所以说,size_t变量不能为负值,否则会出问题
zu% 不能输出负数
<2> 查询指针大小使用sizeof
<3> 使用intptr_t和uintptr_t
这两个类型用来存放指针地址
3、近指针一次寻址64K内存,远指针最多寻址1MB内存
巨指针是规范化的远指针,使用尽可能高的段
三、指针操作符
给指针加上整数
从指针减去整数
两个指针相减
比较指针
函数指针则不一定
1、2 加减整数
注意
<1>如果是指针访问数组,在加减整数的时候,不要数组越界
<2>试图给void指针加1可能会导致语法错误
<3>加减整数,地址值的改变是数据类型的长度和整数值的乘积
3、指针相减
两个指针相减得到的是两个地址的差值,这个差值没有什么卵用,电脑上可以判断数组中的元素顺序
4、比较指针
实际上就是地址的比较
四、指针的常见用法
1、多层间接引用
2、常量和指针
<1>、指向常量的指针 常量的指针
注意不能通过解引指针来改变常量
例子:
int iNum= 5;
const int *pci;
pci = &iNum;
*pci = 200;// 错误,因为指针指向常量,不能够给常量赋值
另外数据类型和const 关键字的顺序不重要
const int *pci;
int const *pci;
<2>、指向非常量的指针,也可以叫指针常量
指针不可变(地址不能变),指向的数据可变,指针是常量
int num;
int *const cpi = #
在这里,cpi必须被初始化为指向非常量变量
cpi 不能被修改
cpi指向的数据可以被修改
无论cpi引用了什么,都能解引cpi然后赋予一个新值
*cpi = limit; // 合法
*cpi = 25; // 合法
但是下面这样做不行
const int limit = 500;
int *const cpi = &limit;
//
int num;
int *const cpi = #
<三>、指向常量的常量指针
(可以理解为一类型的常量指针)
指针本身不能修改(指向地址),
通过指针不能改指向的内容
const int limit = 500;
const int const cpi = &limit;
指向变量的常量指针
int num;
const int const cpci = #
<四>、指向"指向常量的常量指针"的指针
多级引用不是很好理解,洋葱一样
const int limit = 500;
const int * const cpci = &limit;
const int * const * pcpci = &cpci;