日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

__attribute__((packed))

發(fā)布時間:2025/3/21 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 __attribute__((packed)) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. __attribute__ ((packed)) 的作用就是告訴編譯器取消結構在編譯過程中的優(yōu)化對齊,按照實際占用字節(jié)數進行對齊,是GCC特有的語法。這個功能是跟操作系統(tǒng)沒關系,跟編譯器有關,gcc編譯器不是緊湊模式的,我在windows下,用vc的編譯器也不是緊湊的,用tc的編譯器就是緊湊的。例如在gcc下:

#include<stdio.h>
#include<string.h>
typedef struct STudent
{
??? int? SID;
??? char SName;
}SInfo;
typedef struct Student
{
??? int SID;
??? char SName;
}__attribute__((packed)) Sinfo;

int main()
{
??? int length_SInfo = sizeof(SInfo), length_Sinfo = sizeof(Sinfo);
??? printf("%d, %d\n", length_SInfo, length_Sinfo);

}

運行gcc test.c -o test

查看結果./test

結果:8,5

?

其它關于__attribute__的知識:

__attribute__書寫特征是:__attribute__前后都有兩個下劃線,并切后面會緊跟一對原括弧,括弧里面是相應的__attribute__參數。
__attribute__語法格式為:
__attribute__ ((attribute-list))
其位置約束為:
放于聲明的尾部“;”之前。
函數屬性(Function Attribute)
函數屬性可以幫助開發(fā)者把一些特性添加到函數聲明中,從而可以使編譯器在錯誤檢查方面的功能更強大。__attribute__機制也很容易同非GNU應用程序做到兼容之功效。
GNU CC需要使用 –Wall編譯器來擊活該功能,這是控制警告信息的一個很好的方式。

?

下面介紹幾個常見的函數屬性參數。

1、

__attribute__ format
該__attribute__屬性可以給被聲明的函數加上類似printf或者scanf的特征,它可以使編譯器檢查函數聲明和函數實際調用參數之間的格式化字符串是否匹配。該功能十分有用,尤其是處理一些很難發(fā)現的bug。
format的語法格式為:
format (archetype, string-index, first-to-check)
??? format屬性告訴編譯器,按照printf, scanf, strftime或strfmon的參數表格式規(guī)則對該函數的參數進行檢查。“archetype”指定是哪種風格;“string-index”指定傳入函數的第幾個參數是格式化字符串;“first-to-check”指定從函數的第幾個參數開始按上述規(guī)則進行檢查。
具體使用格式如下:
__attribute__((format(printf,m,n)))
__attribute__((format(scanf,m,n)))
其中參數m與n的含義為:
m:第幾個參數為格式化字符串(format string);
n:參數集合中的第一個,即參數“…”里的第一個參數在函數參數總數排在第幾,注意,有時函數參數里還有“隱身”的呢,后面會提到;
在使用上,__attribute__((format(printf,m,n)))是常用的,而另一種卻很少見到。下面舉例說明,其中myprint為自己定義的一個帶有可變參數的函數,其功能類似于printf:
//m=1;n=2
extern void myprint(const char *format,...) __attribute__((format(printf,1,2)));
//m=2;n=3
extern void myprint(int l,const char *format,...) __attribute__((format(printf,2,3)));
需要特別注意的是,如果myprint是一個函數的成員函數,那么m和n的值可有點“懸乎”了,例如:
//m=3;n=4
extern void myprint(int l,const char *format,...) __attribute__((format(printf,3,4)));
其原因是,類成員函數的第一個參數實際上一個“隱身”的“this”指針。(有點C++基礎的都知道點this指針,不知道你在這里還知道嗎?)
這里給出測試用例:attribute.c,代碼如下:
1:
2:extern void myprint(const char *format,...) __attribute__((format(printf,1,2)));
3:
4:void test()
5:{
6:????? myprint("i=%d\n",6);
7:????? myprint("i=%s\n",6);
8:????? myprint("i=%s\n","abc");
9:????? myprint("%s,%d,%d\n",1,2);
10:}

運行$gcc –Wall –c attribute.c attribute后,輸出結果為:

attribute.c: In function `test':
attribute.c:7: warning: format argument is not a pointer (arg 2)
attribute.c:9: warning: format argument is not a pointer (arg 2)
attribute.c:9: warning: too few arguments for format

如果在attribute.c中的函數聲明去掉__attribute__((format(printf,1,2))),再重新編譯,既運行$gcc –Wall –c attribute.c attribute后,則并不會輸出任何警告信息。
注意,默認情況下,編譯器是能識別類似printf的“標準”庫函數。

?

2、

__attribute__ noreturn
該屬性通知編譯器函數從不返回值,當遇到類似函數需要返回值而卻不可能運行到返回值處就已經退出來的情況,該屬性可以避免出現錯誤信息。C庫函數中的abort()和exit()的聲明格式就采用了這種格式,如下所示:

extern void exit(int)?? __attribute__((noreturn));
extern void abort(void) __attribute__((noreturn));

為了方便理解,大家可以參考如下的例子:

//name: noreturn.c ;測試__attribute__((noreturn))
extern void myexit();

int test(int n)
{
??? if ( n > 0 )
???? {
????????? myexit();
?????????? /* 程序不可能到達這里*/
???? }
??? else
????????? return 0;
}

編譯顯示的輸出信息為:

$gcc –Wall –c noreturn.c
noreturn.c: In function `test':
noreturn.c:12: warning: control reaches end of non-void function

警告信息也很好理解,因為你定義了一個有返回值的函數test卻有可能沒有返回值,程序當然不知道怎么辦了!
加上__attribute__((noreturn))則可以很好的處理類似這種問題。把
extern void myexit();
修改為:
extern void myexit() __attribute__((noreturn));
之后,編譯不會再出現警告信息。

?

?

3、

__attribute__ const
該屬性只能用于帶有數值類型參數的函數上。當重復調用帶有數值參數的函數時,由于返回值是相同的,所以此時編譯器可以進行優(yōu)化處理,除第一次需要運算外,其它只需要返回第一次的結果就可以了,進而可以提高效率。該屬性主要適用于沒有靜態(tài)狀態(tài)(static state)和副作用的一些函數,并且返回值僅僅依賴輸入的參數。
為了說明問題,下面舉個非常“糟糕”的例子,該例子將重復調用一個帶有相同參數值的函數,具體如下:

extern int square(int n) __attribute__((const));
...
???? for (i = 0; i < 100; i++ )
???? {
?????????? total += square(5) + i;
???? }

通過添加__attribute__((const))聲明,編譯器只調用了函數一次,以后只是直接得到了相同的一個返回值。
事實上,const參數不能用在帶有指針類型參數的函數中,因為該屬性不但影響函數的參數值,同樣也影響到了參數指向的數據,它可能會對代碼本身產生嚴重甚至是不可恢復的嚴重后果。
并且,帶有該屬性的函數不能有任何副作用或者是靜態(tài)的狀態(tài),所以,類似getchar()或time()的函數是不適合使用該屬性的。
-finstrument-functions

更多的屬性含義參考:
http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html

?

下面還有變量屬性:

1、

aligned (alignment)
該屬性規(guī)定變量或結構體成員的最小的對齊格式,以字節(jié)為單位。例如:

int x __attribute__ ((aligned (16))) = 0;

編譯器將以16字節(jié)(注意是字節(jié)byte不是位bit)對齊的方式分配一個變量。也可以對結構體成員變量設置該屬性,例如,創(chuàng)建一個雙字對齊的int對,可以這么寫:

struct foo { int x[2] __attribute__ ((aligned (8))); };

如上所述,你可以手動指定對齊的格式,同樣,你也可以使用默認的對齊方式。如果aligned后面不緊跟一個指定的數字值,那么編譯器將依據你的目標機器情況使用最大最有益的對齊方式。例如:

short array[3] __attribute__ ((aligned));

選擇針對目標機器最大的對齊方式,可以提高拷貝操作的效率。
aligned屬性使被設置的對象占用更多的空間,相反的,使用packed可以減小對象占用的空間。
需要注意的是,attribute屬性的效力與你的連接器也有關,如果你的連接器最大只支持16字節(jié)對齊,那么你此時定義32字節(jié)對齊也是無濟于事的。

aligned (alignment)
該屬性設定一個指定大小的對齊格式(以字節(jié)為單位),例如:

struct S { short f[3]; } __attribute__ ((aligned (8)));
typedef int more_aligned_int __attribute__ ((aligned (8)));

該聲明將強制編譯器確保(盡它所能)變量類型為struct S或者more-aligned-int的變量在分配空間時采用8字節(jié)對齊方式。
如上所述,你可以手動指定對齊的格式,同樣,你也可以使用默認的對齊方式。如果aligned后面不緊跟一個指定的數字值,那么編譯器將依據你的目標機器情況使用最大最有益的對齊方式。例如:

struct S { short f[3]; } __attribute__ ((aligned));

這里,如果sizeof(short)的大小為2(byte),那么,S的大小就為6。取一個2的次方值,使得該值大于等于6,則該值為8,所以編譯器將設置S類型的對齊方式為8字節(jié)。
aligned屬性使被設置的對象占用更多的空間,相反的,使用packed可以減小對象占用的空間。
需要注意的是,attribute屬性的效力與你的連接器也有關,如果你的連接器最大只支持16字節(jié)對齊,那么你此時定義32字節(jié)對齊也是無濟于事的。

?

?

2、

packed
使用該屬性可以使得變量或者結構體成員使用最小的對齊方式,即對變量是一字節(jié)對齊,對域(field)是位對齊。
下面的例子中,x成員變量使用了該屬性,則其值將緊放置在a的后面:

???? struct test
????? {
??????? char a;
??????? int x[2] __attribute__ ((packed));
????? };

其它可選的屬性值還可以是:cleanup,common,nocommon,deprecated,mode,section,shared,tls_model,transparent_union,unused,vector_size,weak,dllimport,dlexport等,
詳細信息可參考:
http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Variable-Attributes.html#Variable-Attributes
類型屬性(Type Attribute)
關鍵字__attribute__也可以對結構體(struct)或共用體(union)進行屬性設置。大致有六個參數值可以被設定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias。
在使用__attribute__參數時,你也可以在參數的前后都加上“__”(兩個下劃線),例如,使用__aligned__而不是aligned,這樣,你就可以在相應的頭文件里使用它而不用關心頭文件里是否有重名的宏定義。

packed
使用該屬性對struct或者union類型進行定義,設定其類型的每一個變量的內存約束。當用在enum類型定義時,暗示了應該使用最小完整的類型(it indicates that the smallest integral type should be used)。
下面的例子中,my-packed-struct類型的變量數組中的值將會緊緊的靠在一起,但內部的成員變量s不會被“pack”,如果希望內部的成員變量也被packed的話,my-unpacked-struct也需要使用packed進行相應的約束。

struct my_unpacked_struct
{
??? char c;
??? int i;
};
?????
struct my_packed_struct
{
? char c;
? int i;
? struct my_unpacked_struct s;
}__attribute__ ((__packed__));

?

Reference:
1.有關__attribute__的相對簡單的介紹:http://www.unixwiz.net/techtips/gnu-c-attributes.html
2.__attribute__詳細介紹:http://gcc.gnu.org

?

?

總結

以上是生活随笔為你收集整理的__attribute__((packed))的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。