剑指小组2017----西邮Linux兴趣小组纳新面试题讲解(第17题)

来源:互联网 发布:安装python安装方法 编辑:程序博客网 时间:2024/05/21 14:01

17题

struct node{    char a;    short b;    int c;};int main(void){    struct node s;    memset(&s, 0, sizeof(struct node));    s.a = 3;    s.b = 5;    s.c = 7;    struct node *pt = &s;    printf("%d\n",*(int *)pt);    printf("%lld\n",*(long long *)pt);}

关键词—大小端、内存对齐、强制类型转换

内存对齐

首先我们来看这个结构体,先是1字节char,然后2字节short,然后4字节int,那么在内存中的布局应该是

大小端

什么是大小端呢,这里不具体展开,只做最简单的介绍。
我们知道 一个int 类型的数据在计算机中占4个字节(现在的大部分情况),那么如果我写下 int a = 1; 在内存中是怎么存储的呢
? 我们知道应该是000…1, 也就是31个0和一个1,那么这个1是在低地址,还是在高地址呢,我们可以写一个程序验证一下。

#include <stdio.h>int main(void){    int a = 1;    printf("%p\n",&a);    char *p = (char *)&a;    for(int i = 1; i <= 4; i++,p++)        printf("%p %d\n",p,*p);}

结果如下

结果
可以看到我们用一个字符指针p来从a的首地址依次往下读取了4个字节,每次一个。可以看到1是在低地址。

至于我们的计算机究竟是大端还是小端,可以用lscpu 查看

lscpu

可以看到是小端 。

对于小端(也就是上图的结果),我们可以理解为低字节(低位)存放在低地址 对于4字节的int a = 1,1自然是最低位,应该存放在最低地址,也就是首地址。
而大端(如网络传输中的字节序),就是高字节(高位)存放在低地址

回到本题,经过3,5,7 三次的赋值,在内存里究竟是怎样呢?可以先自己画一下。
我们这里直接给出结果,用gdb来查看内存。

这里写图片描述

可以看到按照小端模式在内存中保存的样子。(由于memset() 可以看到a和b中间的一个字节也被清0了 )

强制类型转换

    struct node *pt = &s;    printf("%d\n",*(int *)pt);    printf("%lld\n",*(long long *)pt);

第一句定义pt是一个结构体指针,指向了结构体首地址。
先强制类型转换为一个int型的指针,然后解引用。

这里就牵扯出一个问题 char *int * 有什么区别呢?
可以想到的有类型不同 运算操作不同

那么在解引用时有什么区别呢?
char *解引用自然是一个char也就是一个字节
int * 解引用是一个int,4个字节并且和 int 变量相同,也有大小端之说,或者说在这里,就是按照小端进行计算的。

所以第一个printf我们是从结构体首地址取出4字节按照一个int类型打印。再根据小端模式,这个int值是这样的

(二进制)00000000 00000101 00000000 00000011
(十六进制–由高地址到低地址)00 05 00 03

我们可以算一下十进制,也就是

pow(2,0)+pow(2,1)+pow(2,16)+pow(2,18)

下面的long long *同理 只不过4个字节变成了8个字节。相信聪明的你一定能想明白吧。

原创粉丝点击