前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >粉丝问答一|关于计算机补码和结构体的两个问题

粉丝问答一|关于计算机补码和结构体的两个问题

作者头像
嵌入式与Linux那些事
发布2021-07-12 16:18:11
2890
发布2021-07-12 16:18:11
举报

哈喽,大家好。今天分享下粉丝针对嵌入式软件开发面试知识点总结中的内容提出的两个问题。问题不难,但是容易掉坑里。 而在笔试中,很多大厂都喜欢出这种题目来坑害小伙伴们。所以,大家在笔试前要扎实基础,做题的时候,要看清题目。

问题一

为什么-n=~ (n-1)=~ n+1?

解答

该问题来源于嵌入式软件开发面试知识点总结P141。原问题为:不用除法操作符如何实现两个正整数的除法。

粉丝的疑问在于表达式-n=~ (n-1)=~ n+1 。解决这个问题的核心在于,要知道计算机中是如何存储数值的。

在计算机系统中,数值一律用补码来表示(存储)。主要原因是使用补码可以将符号位和其他位统一处理;同时,减法也可以按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。

如何求补码呢?

  1. 正数的补码 与原码相同。 +9的补码是00001001。
  2. 负数的补码 对其原码逐位取反,但符号位除外;然后整个数加1。 -7的原码为10000111,按位取反为11111000,加1可得11111001。所以-7的补码是11111001。

补码表示方式有很多,以上两个例子都是使用8位的2进制来表示的。此外,还有16位2进制补码表示形式,以及32位2进制补码表示形式等。

如何快速求补码?

从最低位开始至找到的第一个1均不变,符号位不变,这之间的各位“求反”(0变1;1变0)。

原码:1010 1001 补码:1101 0111。

举例

下面,我们举个例子验证下上面的等式。假设n = 10,则可以得到下面的各个表达式。

代码语言:javascript
复制
n:10 = 00001010
-n:-10 = 11110110
n-1:9 = 00001001
~(n-1):-10 = 11110110
~n:-11 = 11110101
~n+1 = 11110110

代码验证

算的对不对呢?可以写个代码验证下。

代码语言:javascript
复制
#include <stdlib.h>
#include <stdio.h>

int PrintBinary(int bi,int len){
 
 int i=0;
 while(i<len){

  int tmp = 1;
  //从最左位开始比较,该位是1
  if((bi & (tmp<<(len-i-1))) != 0){
   printf(" 1 ");
  }
  else{
   printf(" 0 ");
  }
  i++;   
 }
 printf("\n");
        return 0;
}

int main()
{
 int n = 10;
 printf("n=%d\n",n);
 PrintBinary(n,8);
 printf("-n=%d\n",-n);
 PrintBinary(-n,8);
 printf("n-1=%d\n",n-1);
 PrintBinary(n-1,8);
 printf("~(n-1)=%d\n", ~(n-1));
 PrintBinary(~(n-1),8);
 printf("~n=%d\n", ~n);
 PrintBinary(~n,8);
 printf("~n+1=%d\n", ~n+1);
 PrintBinary(~n+1,8);
 return 0;
}

结果如下。

代码语言:javascript
复制
n=10
 0  0  0  0  1  0  1  0
-n=-10
 1  1  1  1  0  1  1  0
n-1=9
 0  0  0  0  1  0  0  1
~(n-1)=-10
 1  1  1  1  0  1  1  0
~n=-11
 1  1  1  1  0  1  0  1
~n+1=-10
 1  1  1  1  0  1  1  0

常用的位运算技巧

  1. -n=~ (n-1)=~ n+1
  2. 获取整数n的二进制中最后一个1:n&(-n)或者n&~(n-1)。例如,n=010100,则-n=101100,n&(-n)= 000100。
  3. 去掉整数n的二进制中最后一个1:n&(n-1),如n=010100,n-1=010011,n&(n-1)=010000。

问题二

结构体所占字节数

该问题来源于嵌入式软件开发面试知识点总结P150。原问题为:指针进行强制类型转换后与地址进行加法运算,结果是什么?

代码语言:javascript
复制
struct BBB
{
  long num;
  char *name;
  short int data;
  char ha;
  short ba[5];
}*p;

在32位机器下, sizeof(struct BBB)=24。但是粉丝算的是28。

解答

char

指针变量

short int

int

unsigned int

float

double

long

long long

unsigned long

32位

1

4

2

4

4

4

8

4

8

4

64位

1

8

2

4

4

4

8

8

8

8

这位粉丝估计是把数据类型所占字节数记错了。

对于32位系统:4+4+2+1+(1)+10+(2)=24

对于64位系统:8+8+2+1+(1)+10+(2)=32

括号中的数字,表示的是为了保证4字节对齐需要填充的字节数。

总结

粉丝的提问,在我能力范围内的,我都会回答。有时候,问题不一定能够及时看到。但是,群里大佬也不少,一般都会有人解答的。

因此,我鼓励大家把问题发到交流群里。大家可以互相学习,互相交流。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式与Linux那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题一
    • 为什么-n=~ (n-1)=~ n+1?
      • 解答
      • 问题二
        • 结构体所占字节数
          • 解答
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档