Linux下的 arm-linux-gcc 与 gcc 关于字节对齐问题

本文详细介绍了GCC编译器中如何使用__attribute__((packed))取消结构体默认对齐,实现紧凑存储,避免填充字节,适用于内存敏感的应用场景。

__attrubte__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

#define __u8    unsigned char
#define __u16   unsigned short

/* __attribute__ ((packed)) 的位置约束是放于声明的尾部“;”之前 */
struct str_struct{
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
} __attribute__ ((packed));

/*  当用到typedef时,要特别注意__attribute__ ((packed))放置的位置,相当于:
  *  typedef struct str_stuct str;
  *  而struct str_struct 就是上面的那个结构。
  */
typedef struct {
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
} __attribute__ ((packed)) str;

/* 在下面这个typedef结构中,__attribute__ ((packed))放在结构名str_temp之后,其作用是被忽略的,注意与结构str的区别。*/
typedef struct {
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
}str_temp __attribute__ ((packed));

typedef struct {
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
}str_nopacked;

int main(void)
{
        printf("sizeof str_struct   = %d/n", sizeof(struct str_struct));
        printf("sizeof str          = %d/n", sizeof(str));
        printf("sizeof str_temp      = %d/n", sizeof(str_temp));
        printf("sizeof str_nopacked = %d/n", sizeof(str_nopacked));
        return 0;
}

编译运行:
[root@localhost root]# ./packedtest   
sizeof str_struct   = 5 
sizeof str          = 5
sizeof str_temp      = 6
sizeof str_nopacked = 6

--------------------------------------------------------------------
GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
__attribute__书写特征是:__attribute__前后都有两个下划线,并且后面会紧跟一对括弧,括弧里面是相应的__attribute__参数。
__attribute__语法格式为:

__attribute__ ((attribute-list))

其位置约束:放于声明的尾部“;”之前。

函数属性(Function Attribute):函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。__attribute__机制也很容易同非GNU应用程序做到兼容之功效。

GNU CC需要使用 –Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

packed属性:使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。

 

//--补充

今天移植usb驱动到uboot中,就发现这个问题。在ads1.2中用__packed修饰的,我一开始把它去掉了。搞了2天没搞出来。后来才发现是这个问题。


方法一:

#include <stdio.h>

#pragma pack(1)
struct abc
{
    double a;
    int    b;
    char   c;
};
#pragma pack()

void main()
{
    printf( "sizeof( struct abc ) = %d\n", sizeof( struct abc ) );
}

以上代码
gcc tBytePadding.c -o tBytePadding
Ubuntu执行结果:sizeof( struct abc ) = 13

/usr/local/arm/2.95.3/bin/arm-linux-gcc -I /usr/local/arm/2.95.3/arm-linux/include tBytePadding.c -o tBytePadding
执行结果:sizeof( struct abc ) = 16 <-- 依然四字对齐了,没有一字节对齐

方法二:

#include <stdio.h>

typedef struct tagabc
{
    double a;
    int    b;
    char   c;
}__attribute__( ( packed, aligned( 1 ) ) ) abc;

void main()
{
    printf( "sizeof( abc ) = %d\n", sizeof( abc ) );
}



#include <stdio.h>

struct abc
{
    double a;
    int    b;
    char   c;
}__attribute__( ( packed, aligned(1) ) );

void main()
{
    printf( "sizeof( struct abc ) = %d\n", sizeof( struct abc ) );
}

以上代码
gcc tBytePadding.c -o tBytePadding
Ubuntu执行结果:sizeof( struct abc ) = 13

/usr/local/arm/2.95.3/bin/arm-linux-gcc -I /usr/local/arm/2.95.3/arm-linux/include tBytePadding.c -o tBytePadding
执行结果:sizeof( struct abc ) = 13

推荐使用方法二的第一种!

注意:
typedef struct tagabc
{
    double a;
    int    b;
    char   c;
}__attribute__( ( packed, aligned( 1 ) ) );

tagabc abc;

以上写法会报此错误:warning: ‘packed’ attribute ignored

typedef struct tagabc
{
    double a;
    int    b;
    char   c;
} abc __attribute__( ( packed, aligned( 1 ) ) );

以上写法也会报此错误:warning: ‘packed’ attribute ignored

分析编译报错原因 /bin/sh ../../libtool --tag=CC --mode=compile arm-ca9-linux-uclibcgnueabihf-gcc -DHAVE_CONFIG_H -I. -I../.. -I. -I.. -I../JudyCommon/ -I/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/usr/include -I/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/include -I/home/lgb/sharedfile/ipc/platform/nvmp/../sdk/soc/nvt9856x/uclibc-toolchain-1.0.32/arm-ca9-linux-uclibcgnueabihf-8.4.01/arm-ca9-linux-uclibcgnueabihf/sysroot/usr/include -DJUDYL -DJUDYGETINLINE -O2 -pipe -fgnu89-inline -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -ftree-vectorize -fno-builtin -fno-common -g -Wno-stringop-truncation -Wno-format-truncation -Wno-sizeof-pointer-div -Wno-stringop-overflow -Wno-format-overflow -Wno-sizeof-pointer-memaccess -g -UJU_64BIT -c -o libinline_la-j__udyLGet.lo `test -f 'j__udyLGet.c' || echo './'`j__udyLGet.c /bin/sh ../../libtool --tag=CC --mode=link arm-ca9-linux-uclibcgnueabihf-gcc -DJUDYL -DNOSMARTJBB -DNOSMARTJBU -DNOSMARTJLB -O2 -pipe -fgnu89-inline -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -ftree-vectorize -fno-builtin -fno-common -g -Wno-stringop-truncation -Wno-format-truncation -Wno-sizeof-pointer-div -Wno-stringop-overflow -Wno-format-overflow -Wno-sizeof-pointer-memaccess -g -UJU_64BIT -L/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/usr/lib -L/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/lib -L/home/lgb/sharedfile/ipc/platform/nvmp/../sdk/soc/nvt9856x/uclibc-toolchain-1.0.32/arm-ca9-linux-uclibcgnueabihf-8.4.01/arm-ca9-linux-uclibcgnueabihf/sysroot/usr/lib -L/home/lgb/sharedfile/ipc/platform/nvmp/../sdk/soc/nvt9856x/uclibc-toolchain-1.0.32/arm-ca9-linux-uclibcgnueabihf-8.4.01/arm-ca9-linux-uclibcgnueabihf/sysroot/lib -o libcount.la libcount_la-JudyLByCount.lo OpenWrt-libtool: compile: arm-ca9-linux-uclibcgnueabihf-gcc -DHAVE_CONFIG_H -I. -I../.. -I. -I.. -I../JudyCommon/ -I/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/usr/include -I/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/include -I/home/lgb/sharedfile/ipc/platform/nvmp/../sdk/soc/nvt9856x/uclibc-toolchain-1.0.32/arm-ca9-linux-uclibcgnueabihf-8.4.01/arm-ca9-linux-uclibcgnueabihf/sysroot/usr/include -DJUDYL -DJUDYGETINLINE -O2 -pipe -fgnu89-inline -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -ftree-vectorize -fno-builtin -fno-common -g -Wno-stringop-truncation -Wno-format-truncation -Wno-sizeof-pointer-div -Wno-stringop-overflow -Wno-format-overflow -Wno-sizeof-pointer-memaccess -g -UJU_64BIT -c j__udyLGet.c -fPIC -DPIC -o .libs/libinline_la-j__udyLGet.o OpenWrt-libtool: link: arm-ca9-linux-uclibcgnueabihf-ar cru .libs/libcount.a .libs/libcount_la-JudyLByCount.o /bin/sh ../../libtool --tag=CC --mode=link arm-ca9-linux-uclibcgnueabihf-gcc -DJUDYL -DJUDYGETINLINE -O2 -pipe -fgnu89-inline -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -ftree-vectorize -fno-builtin -fno-common -g -Wno-stringop-truncation -Wno-format-truncation -Wno-sizeof-pointer-div -Wno-stringop-overflow -Wno-format-overflow -Wno-sizeof-pointer-memaccess -g -UJU_64BIT -L/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/usr/lib -L/home/lgb/sharedfile/ipc/platform/nvmp/staging_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/lib -L/home/lgb/sharedfile/ipc/platform/nvmp/../sdk/soc/nvt9856x/uclibc-toolchain-1.0.32/arm-ca9-linux-uclibcgnueabihf-8.4.01/arm-ca9-linux-uclibcgnueabihf/sysroot/usr/lib -L/home/lgb/sharedfile/ipc/platform/nvmp/../sdk/soc/nvt9856x/uclibc-toolchain-1.0.32/arm-ca9-linux-uclibcgnueabihf-8.4.01/arm-ca9-linux-uclibcgnueabihf/sysroot/lib -o libinline.la libinline_la-j__udyLGet.lo OpenWrt-libtool: link: arm-ca9-linux-uclibcgnueabihf-ranlib .libs/libcount.a OpenWrt-libtool: link: arm-ca9-linux-uclibcgnueabihf-ar cru .libs/libinline.a .libs/libinline_la-j__udyLGet.o OpenWrt-libtool: link: arm-ca9-linux-uclibcgnueabihf-ranlib .libs/libinline.a BUG, in j__L_Leaf2PopToWords, sizes not big enough for object Makefile:618: recipe for target 'JudyLTables.c' failed make[6]: *** [JudyLTables.c] Error 1 make[6]: *** Waiting for unfinished jobs.... OpenWrt-libtool: link: ( cd ".libs" && rm -f "libcount.la" && ln -s "../libcount.la" "libcount.la" ) OpenWrt-libtool: link: ( cd ".libs" && rm -f "libinline.la" && ln -s "../libinline.la" "libinline.la" ) make[6]: Leaving directory '/home/lgb/sharedfile/ipc/platform/nvmp/build_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/libjudy-1.0.5-netdata2/src/JudyL' Makefile:255: recipe for target 'all-recursive' failed make[5]: *** [all-recursive] Error 1 make[5]: Leaving directory '/home/lgb/sharedfile/ipc/platform/nvmp/build_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/libjudy-1.0.5-netdata2/src' Makefile:314: recipe for target 'all-recursive' failed make[4]: *** [all-recursive] Error 1 make[4]: Leaving directory '/home/lgb/sharedfile/ipc/platform/nvmp/build_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/libjudy-1.0.5-netdata2' Makefile:245: recipe for target 'all' failed make[3]: *** [all] Error 2 make[3]: Leaving directory '/home/lgb/sharedfile/ipc/platform/nvmp/build_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/libjudy-1.0.5-netdata2' Makefile:88: recipe for target '/home/lgb/sharedfile/ipc/platform/nvmp/build_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/libjudy-1.0.5-netdata2/.built' failed make[2]: *** [/home/lgb/sharedfile/ipc/platform/nvmp/build_dir/target-arm-ca9-linux-uclibcgnueabihf-cx85v1/libjudy-1.0.5-netdata2/.built] Error 2 make[2]: Leaving directory '/home/lgb/sharedfile/ipc/platform/nvmp/package/libjudy' package/Makefile:105: recipe for target 'package/libjudy/compile' failed make[1]: *** [package/libjudy/compile] Error 2 make[1]: Leaving directory '/home/lgb/sharedfile/ipc/platform/nvmp' /home/lgb/sharedfile/ipc/platform/nvmp/include/toplevel.mk:203: recipe for target 'package/libjudy/compile' failed make: *** [package/libjudy/compile] Error 2
最新发布
01-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值