[C语言基础]6.指针学习

指针

  1. 指针 == 内存编号 == 地址
  2. 口语指针:指针变量,是用来存放内存地址的变量

指针变量:存放地址的变量。

  1. &取出变量的内存真实地址
  2. 把地址存放到一个变量中
  3. 这个变量就是指针变量
int main()  
{  
int a = 10;//在内存中开辟一块空间  
int* p = &a;//取a地址,p就是一个指针变量。
return 0;  
}
a变量占用4个字节的空间
将a的4个字节的第一个字节的地址存放在p变量中
p就是一个指针变量。
int* p
*:p是指针,*p是指针变量-->a
int:a是int类型

32位地址,指针变量大小是4个字节。
64位地址,指针变量大小是8个字节。

指针类型

存数据再内存中是倒着存的,访问是正着访问的

指针类型指针解引用时可访问的字节数
char*1byte
short*2byte
int*4byte

野指针

指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

野指针成因

  1. 指针未初始化(随机找了一块空间)
  2. 指针越界访问(数组越界)
  3. 指针指向的空间释放了(局部变量,进函数创建,出函数销毁)
    如何规避野指针
  4. 指针初始化 int* ptr = NULL; -->空指针,没有指向有效空间,不能直接使用。
  5. 小心指针越界
  6. 指针指向空间释放,及时置NULL
  7. 避免返回局部变量的地址
  8. 指针使用之前检查有效性 if(ptr != NULL)

指针运算

指针± 整数

int main()
{
	int arr[10] = {0};
	int* p = &arr[0];
	int i = 0;
	for(i = 0;i < 10;i++)
	{
		*p = i;//将i赋值给 *p,即arr[i] = i
		p++;//给地址++
		//or
		*(p + i) = i;//在p 的基础上增加
	}
	return 0;
}
arr数组名 == 首元素地址 arr[0] == 指针 p
*(p + i)== *(arr + i) == arr[i] == i[arr] == *(i + arr)

指针-指针

地址 - 地址,前提:指向同一块空间
(指针 - 指针) 的绝对值 得到的是 指针之间的元素个数

int main()
{
	int arr[10] = {0};
	printf("%d", &arr[9] - &arr[0]);//9
	return 0;

}

计算字符串长度

int my_strlen(char* s)
{
	char* start = s;
	while(*s)//a b c d e f /0
	{
		s++;
	}
	return s - start;
}
int main()
{
	char arr[] = "abcdef";//a b c d e f /0
	int len = my_strlen(arr);
	printf("%d", len);
	return 0;
}

指针的关系运算

#define N_VALUES 5  
float values[N_VALUES];  
float *vp;
for(vp = &values[N_VALUES]; vp > &values[0];)  
{  
	*--vp = 0;  
}
代码简化, 这将代码修改如下
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)  
{  
	*vp = 0;  
}
实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证  
它可行。

标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较
但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

指针和数组

#include <stdio.h>  
int main()  
{  
	int arr[10] = {1,2,3,4,5,6,7,8,9,0};  
	printf("%p\n", arr);      //012FFB90
	printf("%p\n", &arr[0]);  //012FFB90
	return 0;  
}

数组名 == 数组首元素的地址 == 指针
数组是连续存放的,是一块连续的空间
可以通过 指针 访问 数组,通过 指针 遍历
&arr 的类型是 int (*)[10],而 arr 的类型是 int *

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int* p = arr;/p存放的是数组首元素的地址
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%p==%p\n", &arr[i], p + i);//010FFDFC==010FFDFC ……
		printf("%d ", *(p + i));//1 2 3 4 5 6 7 8 9 0
	}
	return 0;
}

二级指针

int main()
{
	int a = 10;
	int* p = &a;//*:p是指针,int:a是int类型
	int** pp = &p;//*:pp是指针,int*:p是int*类型
	printf("%d ", *(*pp));//10
	*(*pp) = 100;//*pp-->p;*(*pp)==*p-->a
	printf("%d ", a);//100
	return 0;
}

指针数组

存放指针(地址)的数组
eg:

int arr1[10];//存整形的数组
char arr2[10];//存字符的数组
int* arr3[10];//存整形指针的数组
int main()
{
	char arr1[] = "abcdefghijklmn";
	char arr2[] = "1,2,3,4,5,6,7,8,9,0";
	char arr3[] = "hello world";
	char* parr[] = { arr1,arr2,arr3 };//类型是char*
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s\n", parr[i]);//%s打印只需要知道字符串起始位置,打印到\0
	}
	return 0;
}

指针数组模拟出2维数组

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int* parr[] = { arr1,arr2,arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", parr[i][j]);
			printf("%d ", *(parr[i]+j));//与上等价
		}
		printf("\n");
	}
	return 0;
}

2维数组:在内存中是连续的
指针数组:arr1,arr2,arr3不一定连续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WangRuaRua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值