【C语言】交换奇偶位和 offsetof 宏的实现

简介: 【C语言】交换奇偶位和 offsetof 宏的实现

👉交换奇偶位👈


题目内容:写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。

注:二进制补码的最低位为第一位,最高位为第三十二位。


示例 1:

输入:10

输出:5

解释:10的二进制补码为00000000000000000000000000001010,交换奇偶位后为00000000000000000000000000000101,该二进制补码为5的二进制补码,故输出为5。


思路:交换奇偶位,其实就当于将偶数位右移了一位,奇数位左移了一位。那现在的问题就转化成了如何得到偶数位和奇数位上的数字。如果想要得到奇数位上的数字,只需要让该数字和奇数位都为 1 的数字按位与,就能得到奇数位上的数字。同理,只需要让该数字和偶数位都为 1 的数字按位与,就能得到偶数位上的数字。得到这两个数字之后,对它们进行相应的移位,就能得到交换奇偶位后的结果了。



奇数位上都为 1 的数字

01010101010101010101010101010101

0x55555555

偶数位上都为 1 的数字

10101010101010101010101010101010

0xaaaaaaaa


#include <stdio.h>
#define SWAP(N) ((N & 0xaaaaaaaa) >> 1) + ((N & 0x55555555) << 1)
int Swap(const int num)
{
  return ((num & 0xaaaaaaaa) >> 1) + ((num & 0x55555555) << 1);
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  int ret1 = Swap(n);
  int ret2 = SWAP(n);
  printf("ret1 = %d\n", ret1);
  printf("ret2 = %d\n", ret1);
  return 0;
}

c00715ad63544421bb122d3f0e64eec2.png


👉offsetof 宏👈


题目内容:写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明。

8115d4fad13d4775b30f3618793840f2.png

示例 1:

输入:

b6b3a04fde9d4a5182ece67f61b1c0aa.png


输出:

offsetof(struct S, a) = 0

offsetof(struct S, b) = 0

offsetof(struct S, c) = 0

offsetof(struct S, d) = 0



struct S结构体内存对齐示意图

b7118137729c49d39738d413b348a79f.png


如果对结构体内存对齐这个知识点不熟悉的话,可以看一下这篇博客:【C语言】自定义类型详解。


思路:根据上面的struct S 的结构体内存对齐示意图可以知道,其实偏移量就是相对于起点的位置。所以,我们需要确定一个基准地址(起点)。为了方便,博主将 0 作为基准地址,当然也可以用任意一个数字作为基准地址。确定好基准地址后,我们就需要找到成员变量的地址,那么用成员变量的地址减去基准地址就能够得到结构体中某变量相对于首地址的偏移。


成员变量的地址


&( ( (struct_name*)0 )->mem_name)


#include <stdio.h>
#define OFFSETOF(struct_name, mem_name) (int)&( ( (struct_name*)0 )->mem_name)
struct S
{
  int a;
  short b;
  int c;
  char d;
};
int main()
{
  printf("%d\n", OFFSETOF(struct S, a));
  printf("%d\n", OFFSETOF(struct S, b));
  printf("%d\n", OFFSETOF(struct S, c));
  printf("%d\n", OFFSETOF(struct S, d));
  return 0;
}

5727adf70a11477c882ea8a2a90b46b4.png



👉总结👈


本篇文章主要讲解了如何交换二进制补码的奇偶位和模拟实现offsetof宏。其中模拟实现offsetof宏是百度曾经考过的原题,希望大家能过掌握。如果大家觉得文章写得不错,大家给个三连支持一下哦!谢谢大家啦!💖💝❣️












相关文章
|
20天前
|
C语言
【C语言】全局搜索变量却找不到定义?原来是因为宏!
使用条件编译和 `extern` 来管理全局变量的定义和声明是一种有效的技术,但应谨慎使用。在可能的情况下,应该优先考虑使用局部变量、函数参数和返回值、静态变量或者更高级的封装技术(如结构体和类)来减少全局变量的使用。
31 5
|
4月前
|
编译器 程序员 C语言
C语言 宏
C语言 宏
43 5
|
5月前
|
Linux C语言
C语言宏IS_REACHABLE
C语言宏IS_REACHABLE
46 1
|
6月前
|
C语言
【C语言刷题每日一题】一维数组的交换
【C语言刷题每日一题】一维数组的交换
|
6月前
|
C语言
【C语言刷题系列】交换整数的奇数位和偶数位
【C语言刷题系列】交换整数的奇数位和偶数位
|
6月前
|
安全 编译器 C语言
【C语言进阶篇】offsetof宏的介绍 及其实现
【C语言进阶篇】offsetof宏的介绍 及其实现
|
6月前
|
编译器 程序员 C语言
【C语言进阶篇】assert宏 使用详解
【C语言进阶篇】assert宏 使用详解
|
6月前
|
C语言
【C语言刷题系列】交换两个变量的三种方式
【C语言刷题系列】交换两个变量的三种方式
|
6月前
|
C语言
C语言-----将数组A中的内容和数组B中的内容进行交换。(数组一样大)
C语言-----将数组A中的内容和数组B中的内容进行交换。(数组一样大)
|
6月前
|
C语言
C语言----将数组A中的内容和数组B中的内容进行交换。(数组一样大)
C语言----将数组A中的内容和数组B中的内容进行交换。(数组一样大)