C语言-指针
以下笔记整理自https://www.runoob.com
C指针
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。
type *var-name;
type表示数据类型,var-name是指针变量的名称。星号*用来指定一个变量是指针。
不管是什么数据类型的指针,指针的值得类型都是一样的,都是一个代表内存地址的16进制数。
数据类型的不同,只是指针所指向数据的数据类型不同。
我们可以通过在指针变量前面加星号*来读取指针指向的数据。比如
var=*p;
将指针指向的数据赋给变量var,而不是将指针的值赋var。
NULL指针
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
NULL 指针是一个定义在标准库中的值为零的常量。
#include "stdio.h"
int main(void)
{
int *p = NULL;
printf("p的地址是 %p\r\n" , p);
return 0;
}
执行结果为
p的地址是 0000000000000000
不这样做,没有确切地址赋值时,编译器会随机赋值?
在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。
C指针的算术运算
加减运算
C指针可以进行加减运算,因为她本质上就是一个用数值表示的地址。
内存是按字节组织,只不过数据总线的多少决定了一次性能读取多少字节(整数倍),比如DSPIC33EP的数据存储器是16位,一次可以读取两个字节,也可以分别访问高低字节。
指针的数据类型也决定了指针在运算后加减多少个字节,比如一个char类型指针,自增1后,指向addr+1(1个字节)单元地址,我们称为指向下一个字符位置;一个int类型(32bit),自增1后,指向addr+4地址(4个字节),我们称为指向下一个整数位置。以此类推。
假设定义一个32位整数类型的指针,指向1000地址,进行自增1
p++;
执行完后,指向1004地址。
也就是说:
- 指针每一次加减,都会指向上/下一个元素的存储单元。
- 指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度。
比较
指针可以用关系运算符进行比较,比如在一个数组里面,如果两个指针指向数组元素不同,可以通过指针比较进行条件操作。
例如:
#include "stdio.h"
//#define test
const int MAX=3;
int main(void)
{
#ifdef test
int var[] = {10, 100, 100};
int i,*p;
#else
char var[] = {10, 50, 100};
char i,*p;
#endif
p=var;
while( p <= &var[MAX-1] )
{
printf("存储地址为:var[%d] = %p\r\n", i, p);
printf("存储地址为:var[%d] = %d\r\n", i, *p);
i++;
p++;
}
return 0;
}
执行结果为
存储地址为:var[0] = 000000000062FE00
存储地址为:var[0] = 10
存储地址为:var[1] = 000000000062FE01
存储地址为:var[1] = 50
存储地址为:var[2] = 000000000062FE02
存储地址为:var[2] = 100
可见指针自增1后,指向下一个字符位置。
如果取消预处理#define的注释
#define test
执行结果为
存储地址为:var[0] = 000000000062FE00
存储地址为:var[0] = 10
存储地址为:var[1] = 000000000062FE04
存储地址为:var[1] = 100
存储地址为:var[2] = 000000000062FE08
存储地址为:var[2] = 100
可见指针自增1后,指向下一个整数位置。