一套关于 内存对齐 的C#面试题,做错的人很多!

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一套关于 内存对齐 的C#面试题,做错的人很多!相关的知识,希望对你有一定的参考价值。

这是一套朋友公司的面试题,挺有意思分享一下。

题目:判断下面的 Location1Location2 的结构体大小各是多少?

public struct Location1
    
        public int X;
        public int Y;
        public long Z;
    

    public struct Location2
    
        public int X;
        public long Y;
        public int Z;
    

据反馈 90% 的人说一样大,毕竟从代码看仅仅做了一次 YZ 顺序的交换,那真的是这样吗?可以用 windbg 调试下就好了。

完整代码代码如下:

namespace ConsoleApp2

    class Program
    
        static void Main(string[] args)
        
            Location1 location1;
            Location2 location2;

            location1.X = 10;
            location1.Y = 11;
            location1.Z = 12;

            location2.X = 10;
            location2.Y = 11;
            location2.Z = 12;

            Debugger.Break();
        
    

    public struct Location1
    
        public int X;
        public int Y;
        public long Z;
    

    public struct Location2
    
        public int X;
        public long Z;
        public int Y;
    

windbg 输出结果如下:

0:000> !clrstack -a
OS Thread Id: 0x1750 (0)
        Child SP               IP Call Site
00000000007fef68 00007ff9a84b9ad2 [HelperMethodFrame: 00000000007fef68] System.Diagnostics.Debugger.BreakInternal()
00000000007ff050 00007ff989c0f5ee System.Diagnostics.Debugger.Break()

00000000007ff0a0 00007ff92db5090b ConsoleApp2.Program.Main(System.String[]) [D:\\net5\\ConsoleApp4\\ConsoleApp2\\Program.cs @ 26]
    PARAMETERS:
        args (0x00000000007ff110) = 0x0000000003492cf0
    LOCALS:
        0x00000000007ff0e0 = 0x0000000b0000000a
        0x00000000007ff0c8 = 0x000000000000000a

00000000007ff2f8 00007ff98d086913 [GCFrame: 00000000007ff2f8] 
0:000> dp 0x00000000007ff0c8
00000000`007ff0c8  00000000`0000000a 00000000`0000000c
00000000`007ff0d8  00000000`0000000b 0000000b`0000000a
00000000`007ff0e8  00000000`0000000c 00000000`007ff1f8

由于 是从大到小生长的,所以用 dp 命令的时候, location2 是排在 location1 的前方,可以清楚的看到

  1. location2: 000000000000000a 000000000000000c 000000000000000b 很明显它的 size=3*8=24byte

  2. location1: 0000000b0000000a 000000000000000c 它的 size=2*8=16byte

那为什么会差 8byte 呢?如果有熟悉 C/C++ 的朋友这时候应该知道,其实就是 内存对齐 ,为什么会出现 内存对齐 ?我们知道,内存是按照 byte 编址的,也就是一个地址存放一个byte,但cpu可不是这么玩的,它的一次读取数是根据 地址总线 来的,目前我们 cpu 基本都是 64根数据总线,也就是一次性可以读取 8个byte

为了能够让 cpu 读取效率更高,编译器会适当的进行 padding 操作,目的就是 按8 对齐,如果不对齐的话,cpu可能就会出现读不全,也就导致必须至少两次才能读取完毕的情况,肯定会影响 cpu 效率的,还有一个原因是:有些机器必须对齐访问,否则就会异常,所以编译器为了更好的平台移植性,只能对齐啦!

以上是关于一套关于 内存对齐 的C#面试题,做错的人很多!的主要内容,如果未能解决你的问题,请参考以下文章

转载大部分人都会做错的经典JS闭包面试题

Java不会或做错的面试题总结

JS进阶面试题整理(仅仅整理我做错的题)

前端面试题的做错的题(刷题才更新)

C生万物 | 校招热门考点 —— 结构体内存对齐

90%的人都做错的用户画像,到底应该怎么做?