证券研究院 發表於 2025-12-18 10:12:31

C语言中字节对齐的几种方式小结

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>前言</li><li>一、自然对齐(默认对齐方式)</li><ul class="second_class_ul"><li>1.原理:</li><li>2.举例:</li></ul><li>二、预处理指令</li><ul class="second_class_ul"><li>1.原理:</li><li>2.举例</li></ul><li>三、编译器一种属性语法</li><ul class="second_class_ul"><li>1.原理</li><li>2.举例</li></ul><li>总结</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>前言</h2>
<p><span style="font-family:monospace">C语言调试笔记,C语言中字节对齐的几种方式记录一下</span></p>
<p><strong>字节对齐是指数据存储时按照一定的规则在内存中排列,使得数据的访问效率更高</strong></p>
<p class="maodian"></p><h2>一、自然对齐(默认对齐方式)</h2>
<p class="maodian"></p><p class="maodian"></p><h3>1.原理:</h3>
<p>自然对齐是编译器默认的对齐方式。在这种方式下,数据类型按照其自身的长度进行对齐存储。</p>
<p>例如,<code>char</code>类型(通常为 1 字节)可以从任意地址开始存储,因为它的长度就是 1 字节;</p>
<p><code>short</code>类型(通常为 2 字节)的存储地址是 2 的倍数;</p>
<p><code>int</code>类型(通常为 4 字节)的存储地址是 4 的倍数;</p>
<p><code>double</code>类型(通常为 8 字节)的存储地址是 8 的倍数等。</p>
<p class="maodian"></p><h3>2.举例:</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;stdio.h&gt;
struct NaturalAlignment {
    char c;   // 1字节,地址可以是任意位置
    int i;    // 4字节,会自动对齐到4的倍数地址
    short s;// 2字节,因为前面的int已经是4字节对齐,所以这里也自然对齐
};
int main() {
    struct NaturalAlignment na;
    printf("Size of struct NaturalAlignment: %ld\n", sizeof(na));
    // 输出结果通常为1 + (3 padding) + 4 + 2 = 10字节
    // 其中3字节是为了让int能从4的倍数地址开始存储而填充的字节
    return 0;
}</pre></div>
<p><strong><span>注意! </span></strong>某些编译器可能执行结果是12,这跟32位和64位系统中机器字长有关。但是我们验证的是此种对齐方式</p>
<p class="maodian"></p><h2>二、预处理指令</h2>
<h3>1.原理:</h3>
<p><code>#pragma pack(n)&nbsp;</code>是一种预处理指令,用于指定结构体或联合体成员的对齐方式。</p>
<p>其中<code>n</code>表示对齐字节数,编译器会按照这个指定的字节数来对齐成员。</p>
<p>它会尽量按照不超过<code>n</code>字节的边界来对齐成员,但如果成员本身长度大于<code>n</code>,则按照成员自身长度对齐</p>
<p class="maodian"></p><p class="maodian"></p><h3>2.举例</h3>
<p>代码如下(示例):<code> </code></p>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;stdio.h&gt;
#pragma pack(1)// 指定按1字节对齐
struct PackedAlignment1 {
    char c;
    int i;
    short s;
};
#pragma pack()   // 恢复默认对齐方式
#pragma pack(2)// 指定按2字节对齐
struct PackedAlignment2 {
    char c;
    int i;
    short s;
};
#pragma pack()   // 恢复默认对齐方式
int main() {
    struct PackedAlignment1 pa1;
    struct PackedAlignment2 pa2;
    printf("Size of struct PackedAlignment1: %ld\n", sizeof(pa1));
    // 输出结果为1 + 4 + 2 = 7字节,因为按1字节对齐,没有填充字节
    printf("Size of struct PackedAlignment2: %ld\n", sizeof(pa2));
    // 输出结果为1 + (1 padding) + 4 + 2 = 8字节
    // 因为按2字节对齐,char后填充1字节使int能从2的倍数地址开始存储
    return 0;
}</pre></div>
<p class="maodian"></p><h2>三、编译器一种属性语法</h2>
<p class="maodian"></p><h3>1.原理</h3>
<p>这是 GCC 编译器提供的一种属性语法,用于指定变量或类型的对齐字节数。</p>
<p>它主要用于对结构体、联合体或者变量强制指定对齐方式,<code>n</code>为对齐字节数。</p>
<p>当用于结构体时,整个结构体的大小会是<code>n</code>的倍数。</p>
<h3>2.举例</h3>
<div class="jb51code"><pre class="brush:cpp;">#include &lt;stdio.h&gt;
struct AlignedAttribute {
    char c;
    int i;
    short s;
}__attribute__((aligned(4)));// 指定结构体按4字节对齐
int main() {
    struct AlignedAttribute aa;
    printf("Size of struct AlignedAttribute: %ld\n", sizeof(aa));
    // 输出结果为4 + 4 + 4 = 12字节
    // 因为按4字节对齐,char后填充3字节,short后填充2字节
    // 使整个结构体大小是4的倍数
    return 0;
}</pre></div>
<p class="maodian"></p><h2>总结</h2>
<p>这些字节对齐方式在不同的场景下有不同的用途。在需要精确控制内存布局或者与硬件设备进行数据交互时,合理的字节对齐方式可以确保数据的正确读写和高效传输</p>
<p>到此这篇关于C语言中字节对齐的几种方式小结的文章就介绍到这了,更多相关C语言 字节对齐内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: C语言中字节对齐的几种方式小结