一、什么是指针?
1.1概念
指针也就是内存地址的别名,是用来储存地址的变量。
1.2指针的定义
- 定义一个整型变量:int a=2;
- 定义一个整型指针(地址变量):int* p=&b; //变量p保存b的地址,即p指向b
注:这里有时会见到int* p或者int *p两种写法,这两种写法都是正确的,不过在有时容易混淆。
例如:int* a,b;这里本身是想要定义一个指针变量a和整型变量b,可是写成int*容易被认为是 定义了指针变量a和b;这时写成int *a,b更加易于区分。
二、指针的分类与访问
1.1普通指针
定义:int a=0;int* s=&a;
- 直接访问:a=1;
- 间接访问:*s=10;//解引用 or s=&a;
注: &*s=12; 表示对指针s先解引用,将其指向的内存地址的值设置为12;这样做的目的可以修改 指针所指向的内存地址的值。
*&s=12;这表示将整数值12赋给指针变量s
所指向的地址上的值;实际上,*&s等价于s。
指针+1能力: (可以解答为什么数组下标从0开始的问题)
含义:
int* p=arr;//&arr[0]
int arr[]={1,2,3,4,5};
- p+n:表示偏移sizeof(所致数据类型)*n;
注:arr[n]等价于*(arr+n) 例:arr[1]=*(arr+1)
如图所示偏移量可表示为为 sizeof(int)*1;
1.2指针数组
定义:所谓指针数组即是一个数组内保存的都是指针(地址);
- 例如:char *arr[]={"hello","world","abc"}
如图数组的第一个位置储存的是字符串“hello”的地址,后面以此类推;
注:此时sizeof(arr)=4(指针类型大小)*3(数组内容大小)=12,因为在32位平台里面,指针占4字节
指针数组+1能力
如上图:
- arr[0]=hello;//数组的第一个元素为字符串hello
- *(arr[0]+3)=l;//表示在hello字符串内部偏移量为sizeof(char)*3=3;
- *(arr[1]+0)=w;表示在world字符串内部偏移量为sizeof(char)*0=0;
1.3数组指针
定义:int (*a)[3]本质上是一个指针(由于优先级()>[ ]>*,所以先看括号里面的),指针所指的对象是一个数组;
- 例如: int arr[ ]={1,2,3}; int (*p)[3]=&arr;
数组指针+1能力:
p+1:此时的偏移量为3*sizeof(int)=12个字节
1.4函数指针
定义:定义一个函数指针,指向add调用add 函数,指向mul调用mul函数;
int add(int a,int b)
int mul(int a,int b)
int (*p)(int int);//定义一个函数指针
函数指针的访问:
add(1,2);//直接访问
p = add;
int res = p(1,2);
mul(1,2);//直接访问
p = mul;
res = p(1,2);
1.5const和一级指针结合
1)const int a = 0;//定义常变量
a=10; //error 常变量不可改变
const char* str = "hello"; //字符串常量--数据区 .data
2)const int* p = &val; //限定p所指向的值,具有常性特征(不可以通过*p修改值)
*p = 10; //error
p = # //正确
3)int* const p = &val; 限定p本身具有常性特征(不可以通过p来修改值)
p = &a; //error
*p = b;
4)const int* const p = &a; //双重限定
1.6数据存储模式
1)大端存储模式
定义:低位数据存放在高地址位置(低高)
以一字节为例:
2) 小端存储模式
定义:低位数据存放在低地址位置(低低)
以一字节为例:
代码实现:
#include<stdio.h>
int main()
{
int val = 0x12345678;
char* p = (char*)&val;
*p == 0x12 ? printf("大端存储模式") : printf("小端存储模式");
return 0;
} //Windows输出结果应该为小端存储模式