【C】940/bit1-7指针初阶

文章详细介绍了C语言中的指针概念,包括指针的内存表示、不同类型的指针、指针大小与其类型无关、指针解引用的权限和步长,以及野指针的产生原因和避免方法。此外,还讨论了指针运算、指针与数组的关系、二级指针和指针数组的使用。
摘要由CSDN通过智能技术生成

【参考课程:B站  BV1cq4y1U7sg  BV1Vm4y1r7jY】

目录

指针是什么

指针和指针类型

指针大小与指针类型无关

指针类型决定了指针解引用时的访问权限有多大

指针类型决定了指针走一步的步长有多大

野指针

野指针产生的原因

如何规避野指针

指针运算

指针 + - 整数 \\ 指针的关系运算(比大小)

指针 - 指针

【练习】编写函数求字符串的长度

指针和数组

二级指针

指针数组


指针是什么

内存单元的编号--地址(地址指向内存单元)--地址也被称为指针

//存放地址的变量--指针变量

*指针的大小:在32位平台4个字节,在64位平台8个字节

指针和指针类型

指针大小指针类型无关

#include<stdio.h>
int main()
{	//【64位平台】
	printf("%lld\n", sizeof(int*)); //8
	printf("%lld\n", sizeof(float*)); //8
	printf("%lld\n", sizeof(char*)); //8
	printf("%lld\n", sizeof(double*)); //8
	printf("%lld\n", sizeof(short*)); //8
	printf("%lld\n", sizeof(long long*)); //8
	printf("%lld\n", sizeof(long*)); //8
	return 0;
}

指针类型决定了指针解引用时的访问权限有多大

int main()
{
	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;
	return 0;
}
int main()
{
	int a = 0x11223344;
	char* pc = &a;
	*pc = 0;
	return 0;
}

指针类型决定了指针走一步的步长有多大

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* pi = arr;
	char* pc = arr;
	printf("%p\n", pi);
	printf("%p\n", pi+1);

	printf("%p\n", pc);
	printf("%p\n", pc+1);
	return 0;
}

 

//指针+n   向前走n步

//指针 - n   向后走n步

野指针

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

野指针产生的原因

  1. 指针未初始化
    int main()
    {
    	int* p;//p是一个局部的指针变量,局部不初始化--默认为随机值
    	*p = 20;//非法访问内存了 //此处p为【野指针】
    	return 0;
    }
  2. 指针越界访问

    int main()
    {
    	int arr[10] = { 1 };
    	int* p = arr;
    	int i = 0;
    	for (i = 0; i <= 10; i++)//i==10时越过arr开辟的内存空间了
    	{
    		*p = i;
    		p++;
    	}
    	return 0;
    }
  3. 指针指向的空间释放了→非法访问

    int* test()
    {
    	int a = 10; //a是函数test的局部变量
    	return &a; //a在离开test时即销毁→其开辟的内存空间被释放
    }
    int main()
    {
    	int* p = test(); //p储存的是a的地址,但离开test函数a即被销毁
    	*p = 20; //再通过p储存的(曾经a的)地址已经无法访问a了→这里的p是一个【野指针】
    	return 0;
    }

如何规避野指针

  1. 初始化指针
    #include<stdio.h> //包含NULL的定义
    int main()
    {
    //当不知道p应该初始化为什么地址时,直接初始化为NULL
    	int* p = NULL; //此处NULL定义:#define NULL ((void *)0)
    //知道p应该初始化为什么地址
    	int a = 10;
    	int* pa = &a;
    	return 0;
    }
  2. 小心指针越界

    c语言本身不会检查越界,需要我们自己注意

  3. 指针指向空间释放及时置NULL
  4. 指针使用之前检查有效性
    #include<stdio.h>
    int main()
    {
    	//初始化指针
    	int* p = NULL;//空指针也不能直接用//把p初始化为空指针方便检查指针有效性
    	//检查指针有效性
    	if (p != NULL)
    		*p = 10;
    	return 0;
    }

指针运算

指针 + - 整数 \\ 指针的关系运算(比大小)

//指针+n   向前走n步    //指针 - n   向后走n步

#include<stdio.h>
int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int* p = arr;
	int* p9 = arr + 9; //指针加整数
	for (p=arr;p <= p9;p++) //指针的关系运算
	{
		printf("%d ", *p);
	} //程序结果:将arr数列打印出来
	return 0;
}

*标注规定允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较[这样比较不算越界],但是不允许与指向第一个元素之前的那个内存位置的指针进行比较

指针 - 指针

指针相减得到的是两个指针之间的元素个数

//指针相减的前提两个指针指向同一块空间

#include<stdio.h>
int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	printf("%d\n", &arr[9] - &arr[0]); //9
	return 0;
}
【练习】编写函数求字符串的长度

方法一:函数递归

方法二:计数器

#include<stdio.h>
int main()
{
	char ch[] = "mettri";//[m][e][t][t][r][i][\0]//计数不计[\0]
	int my_strlen(char*);
	printf("%d\n", my_strlen(ch));//数组名-数组首元素地址
	return 0;
}
int my_strlen(char* str)
{
	int c = 0;
	for (; *str != '\0'; str++)
	{
		c++;
	}
	return c;
}

方法三:指针运算

#include<stdio.h>
int main()
{
	char ch[] = "mettri";//[m][e][t][t][r][i][\0]
	int my_strlen(char*);
	printf("%d\n", my_strlen(ch));//数组名-数组首元素地址
	return 0;
}
int my_strlen(char* str)
{
	char* start = str;
	for (; *str != '\0'; str++);
	return str - start;
}

指针和数组

数组名是数组首元素地址

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	//通过指针遍历数组
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i)); //打印数组所有元素
        // *(p + i) <==> arr[i]
	}
	return 0;
}

二级指针

指针变量也是变量,是变量就有地址
二级指针--存放指针变量地址的指针

#include<stdio.h>
int main()
{
	int a = 6;
	int* pa = &a; //pa--指针变量--一级指针
	int** ppa = &pa; //ppa--二级指针
   //解引用二级指针  //*ppa <==> pa //**ppa <==> a
	printf("%d\n", **ppa); //输出 6
	return 0;
}

指针数组

指针数组--存放指针的数组

int main()
{
	int* parr[5]; //存放整型指针的数组-parr
	char* pch[6]; //存放字符型指针的数组-pch
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值