【C语言深度解剖】预定义章节经典面试题讲解(offsetof宏模拟实现)【超详细的解释和注释】

【C语言深度解剖】预定义章节经典面试题讲解(offsetof宏模拟实现)【超详细的解释和注释】

那么这里博主先安利一下一些干货满满的专栏啦!

作者: #西城s
这是我的主页:#西城s
在食用这篇博客之前,博主在这里介绍一下其它高质量的编程学习栏目:
数据结构专栏:数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏Leetcode想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!
C的深度解剖专栏:C语言的深度解剖想要深度学习C语言里面所蕴含的各种智慧,各种功能的底层实现的初学者们,相信这个专栏对你们会有帮助的!

今天博主将带大家做一些预定义章节的面试题,带大家熟悉和深度掌握预定义章节
在这里插入图片描述

本篇位不收藏必后悔系列篇~

前言

关于预定义内容的两篇详细介绍,同样是干货满满的文章,不要错过噢~

【C语言深度解剖】一篇解决程序的环境【编译+链接详解】让面试官给我们竖起大拇指
【预定义】C语言预定义代码(宏、条件编译等)内容介绍【最全的保姆级别教程】

题目1

  • 设有以下宏定义:
    #define N 4
    #define Y(n) ((N+2)*n) (这种定义在编程规范中是严格禁止的)则执行语句:z = 2 * (N + Y(5 + 1)); 后,z的值为____

这题考察的其实是对宏在预处理阶段的替换方式的理解:宏在预处理阶段,是进行原封不动的替换的。
如果对这方面内容有疑问的伙伴们,可以通过博主的传送门食用上面两篇文章,这里面有非常非常详细的讲解:

所以这里宏的调用进行原封不动的替换后的结果为:
2*(4+((4+2)*5+1)

#define N 4
#define Y(n) ((N+2)*n)
int main() {
    
    
	int z = 2 * (N + Y(5 + 1));
	//2*(4+((4+2)*5+1)
	//70
	printf("%d\n", z);
	return 0;
}

实现宏-交换一个数二进制位中奇数位和偶数位

思考:
我们要交换奇数位和偶数位,首先我们先要将某个数的奇数位和偶数位提取出来吧

  • 首先,我们发现,一个数字比如15:
    00000000000000000000000000001111如果按位与上一个01010101...0101这样一个数字,就可以将数字二进制中的奇数位提取出来。
  • 同理,我们发现,一个数字按位与上一个1010....1010这样一个数字之后,我们就可以将它的偶数位提取出来
  • 01010101...01这个数字表示成16进制就是0x55555555,同理,101010...1010这个数字表示成16进制就是0xaaaaaaaa
  • 当我们分别按位与完之后,奇数位向左移一位,偶数位向右移一位,再相加,我们就能得到我们的结果了。
//写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。
#if 1
#define __SWAP_BIT(num) num=((num&0x55555555)<<1)+((num&0xaaaaaaaa)>>1)
int main() {
    
    
	int num = 10;
	//00000000000000000000000000001111
	//我们发现,我们只需要按位与一个01010101...01的数字,奇数位就留下了
	//同样,如果将0101...01这个数字向左移动一位,就可以再按位与num就可以留下偶数位了
	//01010101010101010101010101010101
	//0x55555555
	__SWAP_BIT(num);
	printf("%d\n", num);
	return 0;
}
#endif

offsetof宏的模拟实现

offsetof宏的使用

作用:计算结构体中某变量相对于首地址的偏移
所要包含的头文件#include<stddef.h>

图片来自www.cplusplus.com

使用举例:
这里的输出结果涉及到结构体内存对齐方面的内容,伙伴们可以自行了解一下先,后面博主会专门出一期博客讲解这方面的内容。

#include<stddef.h>
struct S {
    
    
	int a;
	char c;
	double d;
};
int main() {
    
    
	printf("%d\n", offsetof(struct S, a));//0
	printf("%d\n", offsetof(struct S, c));//4
	printf("%d\n", offsetof(struct S, d));//8
	return 0;
}

模拟实现:
实现:#define __OFFSETOF(st_type,mem_name) (size_t)&(((st_type*)0)->mem_name)

#include<stddef.h>
//写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明
//考察:offsetof宏的实现
struct S {
    
    
	int a;
	char c;
	double d;
};
#define __OFFSETOF(st_type,mem_name) (size_t)&(((st_type*)0)->mem_name)
int main() {
    
    
	printf("%d\n", __OFFSETOF(struct S, a));
	printf("%d\n", __OFFSETOF(struct S, c));
	printf("%d\n", __OFFSETOF(struct S, d));
	return 0;
}

尾声

到这里就是本期博客的全部内容了,当然,关于这方面的具体内容知识点,可以通过博主通过的传送门进行详细了解噢~
【C语言深度解剖】一篇解决程序的环境【编译+链接详解】让面试官给我们竖起大拇指
【预定义】C语言预定义代码(宏、条件编译等)内容介绍【最全的保姆级别教程】
如果你感觉这篇博客对你有帮助的话,不要忘了一键三连:点赞收藏关注噢~

猜你喜欢

转载自blog.csdn.net/Yu_Cblog/article/details/124262640