内存地址
- 字节:字节是内存的容量单位,英文称为 byte,一个字节有8位,即 1byte = 8bits
- 地址:系统为了便于区分每一个字节而对它们逐一进行的编号,称为内存地址,简称地址。
基地址
- 单字节数据:对于单字节数据而言,其地址就是其字节编号。
- 多字节数据:对于多字节数据而言,期地址是其所有字节中编号最小的那个,称为基地址。
取址符
- 每个变量都是一块内存,都可以通过取址符 & 获取其地址
- 注意:
- 虽然不同的变量的尺寸是不同的,但是他们的地址的尺寸确实一样的。
- 不同的地址虽然形式上看起来是一样的,但由于他们代表的内存尺寸和类型都不同,因此它们在逻辑上是严格区分的。
int a = 100;
printf("整型变量 a 的地址是: %p\n", &a);
char c = 'x';
printf("字符变量 c 的地址是: %p\n", &c);
double f = 3.14;
printf("浮点变量 f 的地址是: %p\n", &f);
指针的概念
由于翻译的问题,以及口语表达的习惯,在日常表述中,指针在不同的场合会代表以下几个含义:
- 指地址
- 比如变量
a
的地址&a
,这是一个地址当然也是一个指针 - 我们可以说指针 &a 指向变量 a。
- 比如变量
- 指指针变量
- 比如
int *p;
此处变量p是指针变量,又常被简称指针。
- 比如
指针的定义
int *p1; // 用于存储 int 型数据的地址,p1 被称为 int 型指针,或称整型指针
char *p2; // 用于存储 char 型数据的地址,p2 被称为 char 型指针,或称字符指针
double *p3; // 用于存储double型数据的地址,p3 被称为 double 型指针
指针的赋值
赋给指针的地址,类型需跟指针的类型相匹配。
int a = 100;
p1 = &a; // 将一个整型地址,赋值给整型指针p1
char c = 'x';
p2 = &c; // 将一个字符地址,赋值给字符指针p2
double f = 3.14;
p3 = &f; // 将一个浮点地址,赋值给浮点指针p3
指针的索引
所谓索引,指的是通过指针,取得其指向的目标
- 指针的尺寸
- 指针尺寸指的是指针所占内存的字节数
- 指针所占内存,取决于地址的长度,而地址的长度则取决于系统寻址范围,即字长
- 结论:指针尺寸只跟系统的字长有关,跟具体的指针的类型无关
*p1 = 200; // 将 p1 指向的目标(即a)修改为200,等价于 a = 200;
*p2 = 'y'; // 将 p2 指向的目标(即c)修改为'y',等价于 c = 'y';
*p3 = 6.6; // 将 p3 指向的目标(即f)修改为6.6,等价于 f = 6.6;
指针运算
- 指针加法意味着地址向上移动若干个目标
- 指针减法意味着地址向下移动若干个目标
int a = 100;
int *p = &a; // 指针 p 指向整型变量 a
int *k1 = p + 2; // 向上移动 2 个目标(2个int型数据)
int *k2 = p - 3; // 向下移动 3 个目标(3个int型数据)