初识指针·

指针是什么

1.指针是内存中最小的单元编号,也就是地址(指针就是地址)

2.平时口语说的指针,通常指指针变量,是用来存放地址的变量

内存

 指针变量

我们可以通过&取出变量的内存(地址),把地址放在变量中

#include <stdio.h>
int main()
{
 int a = 10;//在内存中开辟一块空间
 int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
    //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
中,p就是一个之指针变量。
 return 0; }

取出变量的地址实际上是取出第一个字节的地址

总结

 那么32根地址线 能产生2的32次方个地址

每个地址标识一个字节,那我们就可以给 (2^32Byte == 2^32/1024KB == 
2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB) 4G的空闲进行编址。
同样的方法,那64位机器,如果给64根地址线,那能编址多大空间,自己计算。

2^32 * 2^ 32=4*4GB=16GB

到这里我们就能明白

 

 

 

 

总结

指针是用来存放地址的,地址是唯一表示一块地址空间的

地址的大小在32位平台是4个字节,64位平台是8个字节 

指针和指针类型

char  *pc = NULL;
int   *pi = NULL;
short *ps = NULL;
long  *pl = NULL;
float *pf = NULL;
double *pd = NULL;

指针不同的类型决定了指针解引用时 能访问地址的字节大小

 

 指针加减整数

指针的类型决定了指针走一步能走几个字节

int main()
{
	int a = 10;
	int*pa = &a;
	char* pc = &a;

	printf("%p\n", pa);
	printf("%p\n", pc);

	printf("%p\n", pa+1);
	printf("%p\n", pc+1);

	return 0;
}

 

float values[5];
float *vp;
for (vp = &values[0]; vp < &values[5];)
{
     *vp++ =0 ; 
}

数组内存中的地址存放  

讨论*和++的关系

可以理解为后置加加时先用指针p,前置加加时根据从右到左顺序

 

 

指针的解引用

 指针的类型决定了,指针解引用时能有多大权限(操作几个字节)

char *访问一个字节,int *访问四个字节

    int arr[10] = { 0 };

	如果希望按照一个整型的形式访问
	int* p = arr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*p = 0x11223344;
		p++;
	}
	假设你希望,你访问这个40个字节的时候,是以字节为单位访问
	char* p = (char*)arr;//int*
	int i = 0;
	for (i = 0; i < 40; i++)
	{
		*p = 'x';
		p++;
	}
int* test()
{
	int a = 10;
	printf("%d\n", a);
	return &a;
}
int main()
{
	int*p = test();
	*p = 100;
}

将变量a销毁后将a的地址传给p,此时p就是&a,*p的地址是指针地址

野指针

野指针形成原因

1.未初始化

2.指针越界访问

3.指针指向的空间释放了

如何规避空指针

 

 空指针不能解引用因此要写库函数assert  对应头文件为: assert.h

指针 减 指针

 不使用变量的情况下构造my_strlen函数

int my_strlen(char* str)
{
	char* start = str;
	while (*str)
	{
		str++;
	}
	return str - start;
}

int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d\n", len);
}

 

int main()
{
	int arr[10] = { 0 };

	printf("%d\n", &arr[0] - &arr[9]);

	return 0;
}

指针的关系运算

一般情况下不能用以下方法写

for(vp = &values[N_VALUES]; vp > &values[0];)
{
    *--vp = 0; 
}

for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) 
{
    *vp = 0; 
}

标准规定

 

 指针和数组

数组名字是首元素地址

 

	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr+1);

	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0]+1);

	printf("%p\n", &arr);
	printf("%p\n", &arr+1);

 二级指针

	int a = 10;
	int* pa = &a;//pa是指针变量(一级指针)
	int** ppa = &pa;//ppa是一个二级指针
	
	int*** pppa = &ppa;//pppa就是三级指针

 二级指针的运算

已知int *pa=&b; int* *pa=&pa;

*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa ,*ppa 其实访问的就是 pa .


int b = 20; *ppa = &b;  //等价于 pa = &b;
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .

**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

指针数组

就是一个数组存放了多个指针

 一维数组

    //int arr[5];//指针数组 - 存放整型的数组
	//char ch[6];//字符数组 -存放字符的数组

	int a = 10;
	int b = 11;
	int c = 12;
	int d = 13;
	int e = 14;
	int* arr2[5] = {&a, &b, &c, &d, &e};//指针数组

	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", *(arr2[i]));
	}

二维数组

    int data1[] = { 1,2,3,4,5 };
	int data2[] = { 2,3,4,5,6 };
	int data3[] = { 3,4,5,6,7 };

	//arr就是一个指针数组
	int* arr[3] = { data1 ,data2, data3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值