【C语言修炼手册】(六)指针和结构体

指针大小在32位平台上是4个字节,在64位平台上是8个字节
既然指针大小无论类型都是一样的,那么为什么不存在一个通用类型指针呢?

指针类型存在的意义

	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;

运行后:
在这里插入图片描述

	int a = 0x11223344;
	char* pa = &a;
	*pa = 0;

运行后:
在这里插入图片描述
可见,指针类型决定了解引用时权限的大小

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

在这里插入图片描述
可见,指针类型决定了指针向前和向后走一步有多大

野指针

指针指向方向未知

造成野指针原因

  1. 指针未初始化
int main()
{
	int* p;//属于局部指针变量,需初始化
	*p = 20;
	return 0;
}
  1. 指针越界
int main()
{
	int* p;
	*p = 20;

	int arr[10] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		*p = i;
		p++;
	}
}

3.指针指向的空间释放

int* test()
{
	int a = 10;
	return &a;
}
int main()
{
	int* p = test();
	*p = 20;
	return 0;
}

使用完test()函数后,a的地址被返给p,然后a的地址被释放掉,此时将20赋给*p,会造成冲突。

如何避免野指针

1.指针初始化
不知道初始化为何时,可以直接初始化为NULL

但要注意:
不能乱用NULL指针。对一个NULL指针进行解引用操作是非法的。在对指针进行解引用操作之前,必须首先确保它并非NULL指针

2.注意指针越界问题
3.及时放置NULL
4.指针使用之前检查有效性

指针运算

  • 指针±整数
  • 指针-指针
  • 指针的关系运算

指针+-整数

指针-指针

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", &arr[9] - &arr[0]); //9
	return 0;
}

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

#include<stdio.h>
int my_strlen(char* str)
{
	char* start = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - start;
}
int main()
{
	int len = my_strlen("abc");
	printf("%d\n", len); //3
	return 0;
}

数组和指针

&arr[i] <=> *(arr+i)

等价关系
arr[2] <==>*(arr+2) <==> *(p+2) <==> *(2+p)  <==> *(2+arr) <==>2[arr]

[ ]是一个操作符 ,因此可以进行交换
对于编译器来说,这些形式没有区别,但是我们平时在写代码时,还是应该注意程序的可读性!,不要随便写。

结构体

struct Stu
{
	char name[20];
	int age;
	char id[20];
}s1,s2;//全局变量

int main()
{
	struct Stu s; //局部变量
	return 0;
}

结构体传参

print(s);//传值调用
print(&s);//传址调用

传址调用效率比传值调用高

传值调用需要将参数的一份拷贝传递给函数,将要开辟空间。这涉及到栈区的使用。因此,传址调用比传值调用效率更高。当然,传址调用也有一定的风险,体现在函数会对调用程序的结构变量进行修改。(有时候我们并不想要修改)

const修饰指针

const int* p = &num;
int * const p = &num;
const int * const p;
int const * const p;

const如果放在*的左边,修饰的是 *p ,表示 指针指向的内容 ,是不能通过指针来改变的,不过指针变量本身是可以修改的。
const如果放在 的右边,修饰的是 p ,表示指针变量本身,是不能通过指针来改变的,不过指针指向的内容是可以修改的。
const既放在
的左边,const又放在 *的右边,表示指针本身和它指向的数据都有可能是只读的


栈区小tips

栈区使用习惯:先使用高地址,再使用低地址

由于局部变量是放在栈区的,所以创建局部变量时,先创建的变量先放在高地址

数组随着下标的增长地址是由低到高变化的。 因此,数组越界就有可能覆盖掉局部变量。

从这一角度来看,这也是数组越界访问错误的原因之一。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值