2024年最新掌握C语言指针,轻松解锁代码高效性与灵活性(上),binder机制面试题

本文分享了一篇关于网络安全面试的指南,包含160多个面试题目,适合求职者特别是有1-3年经验的跳槽者准备,同时推荐了系统的网络安全学习路径和资源,以及指针、const和assert等IT技术概念的讲解。
摘要由CSDN通过智能技术生成

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

	int a = 1;//第一个客户,&a为0x00000001
	int b = 2;//第二个客户,&b为0x00000002
	int c = 3;//第三个客户,&c为0x00000003

然后我们可以通过指针变量把他们地址存储进去

	int* pa = &a;//把a的地址存进去
	int* pb = &b;//把b的地址存进去
	int* pc = &c;//把c的地址存进去

在酒店中,我们可以通过门牌号准确找到每个客户。同理,我们也可以通过每个地址准确找到每个变量。

	printf("a=%db=%dc=%d", *pa, *pb, *pc);//通过*解引用地址找到对应的值

输出结果 a=1 b=2 c=3

并且我们可以通过指针变量进行赋值。

*pa = 4;
*pb = 5;
*pc = 6;
printf("a=%d b=%d c=%d\n", *pa, *pb, *pc);

输出结果:a=4 b=5 c=6

1.4 void*指针和NULL

(1)void*是一种特殊的指针类型,它可以指向任意类型的数据,就是说可以用任意类型的指针对 void 指针赋值。

void*p1;
int*p2;
p1=p2;//这是被允许的

  • 但是却不能把void*指针赋值给任意指针类型,也不能直接对其解引用
void*p1;
int *p2;
p2=p1;//不能这样赋值
*p1//不能直接对void*解引用

(2)NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址会报错

int*p=NULL;//初始化指针

1.5 指针变量的大小

我们知道,现在常见的计算机分为32位机器64位机器。32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4个字节才能存储。同理,64位机器需要8个字节才能存储。

我们可以通过以下代码来验证一下。

int main()
{
	printf("%zd ", sizeof(char*));
	printf("%zd ", sizeof(short*));
	printf("%zd ", sizeof(int*));
	printf("%zd ", sizeof(double*));
	return 0;
}

输出结果:

32位机器:4 4 4 4

64位机器:8 8 8 8

2. 指针的基本运算

2.1 指针±整数

我们先观察一下如下代码的地址变化

#include <stdio.h>
int main()
{
	int n = 10;
	char* p1 = (char*)&n;//将int*强转为char*
	int* p2 = &n;
	printf("%p\n", &n);
	printf("%p\n", p1);
	printf("%p\n", p1 + 1);//p1向后移动一位
	printf("%p\n", p2);
	printf("%p\n", p2 + 1);//p2向后移动一位
	return 0;
}

输出 :

&n=005DF8D4
p1=005DF8D4
p1+1=005DF8D5
p2=005DF8D4
p2+1=005DF8D8

我们可以看出, char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。由此我们得出结论:指针的类型决定了指针向前或者向后⾛⼀步有多⼤(距离)。

  • 因为每次代码运行时,系统都会重新分配内存,所以输出结果每次都不会一样,但是规律是一样的

我们知道数组在内存中是连续存储的(地址由低到高),所以我们只需要只要首元素的地址就能找到数组所有元素的地址,而一维数组的数组名恰恰就是我们首元素的地址。

 假设有数组int arr[10]={1,2,3,4,5,6,7,8,9,10} 

arr12345678910
下标0123456789

那我们如何通过指针访问每个元素呢?

代码参考如下:

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];//&arr[0]=arr
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));//因为数组元素连续存储,所以可以通过+-整数找到之后元素
	}
	return 0;
}

输出结果:1 2 3 4 5 6 7 8 9 10

2.2 指针-指针

指针-指针其实是指在同一空间内,两个指针之间的元素个数

知道这点之后,我们可不可以自己实现一个字符串库函数strlen()呢?

思路如下:

思路:首先定义两个指针p1,p2,让两个指针指向首元素,然后让一个指针p2循环++,直到指向‘\0’就停止,最后返回p2-p1,就能得到字符串的长度

img

代码如下:

int my_strlen(char* p1)
{
	char* p2 = p1;//使两个指针都指向首元素
	while (*p2)
	{
		p2++;
	}
	return p2 - p1;//返回两指针直接的元素的个数就是其长度
}
int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);//计算arr字符串的长度
	printf("%d\n", len);
	return 0;
}

2.3 指针的关系运算

我们知道了指针变量本质是存放的地址,而地址本质就是十六进制的整数,所以指针变量也是可以比较大小的

代码示例:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	while (p < arr + sz) //指针的⼤⼩⽐较
	{
		printf("%d ", *p);//打印数组每个元素
		p++;
	}
	return 0;
}

3. const修饰

我们知道变量是可以改变的,但是在有些场景下,我们不希望变量改变,那我们该怎么办呢?这就是我们接下来要讲的const的作用啦。

3.1 const修饰变量

简单来说,经过const修饰的变量,可以当做一个常量,而常量是不能改变的。

	int a = 1;//a可修改的
	const int b = 2;
	b=3;//b不可修改的

但是可以通过指针间接修改.

代码如下:

int main()
{
	const int b = 2;
	int* p = &b;
	*p = 3;//通过指针间接修改
	return 0;
}

3.2 const修饰指针

我们知道const的作用后,就可以看看下面几段代码。

	int a = 10;
	const int* p = &a;
	*p = 20;//是否可以
	p = p + 1;//是否可以

通过测试我们发现,*p无法改变成20,但是p可以改变成p+1.

那如果把const调换一下位置,又会出现什么情况呢~

	int a = 10;
    int* const p = &a;
	*p = 20;//是否可以
	p = p + 1;//是否可以

再次测试之后我们发现,*p可以被赋值为20,但是p不能赋值为p+1了

通过上述测试,我们大致可以总结出两个结论。

• const如果放在的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。但是指针变量本⾝的内容可变。
• const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。

4. assert断言

assert是一个宏,它的头文件为<assert.h>,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为**“断⾔**”。

举一个简单的例子:

assert(a>0);

  1. 如果a的确大于0,assert判断为真,就会通过。
  2. 如果a不大于0,assert判断为假,就会报错。

所以assert常常用于检查空指针问题,以防止程序因为空指针的问题而出错。

int *p=NULL;
assert(p);//空指针是0,0为假,就会报错

5. 传值调用与传址调用

5.1 传值调用

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值