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

这篇博客介绍了Linux兴趣小组的面试题,涉及内存对齐的概念,解释了大小端存储模式,并通过实例探讨了强制类型转换的影响。文章通过gdb查看内存布局,帮助理解不同类型指针解引用的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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个字节。相信聪明的你一定能想明白吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值