通常在PC上寫程式時,很少會去管struct會佔掉多少記憶體。
當要使用到時,也不會想去用手算到底佔掉多少,大多是直接使用sizeof來做計算。
然而sizeof計算出來的值往往不會如我們想的一樣。因為compiler為了效能考量,會自動地為我們
做最佳化,也就是資料對齊。為了這個目的,compiler會為struct多準備一些記憶體。
我們可以看以下的code:
struct ABC {
int index;
char name[6];
int score;
};

struct DEF{
int att;
char name[3];
};

int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;

}
說明:
1. 若我們直接去計算struct ABC和strcut DEF時,
struct ABC = 4 + 6 + 4 = 14 (struct ABC用掉14個byte)
strcut DEF = 4 + 3 = 7 (struct DEF用掉7個byte)
2. 但真的是這樣嗎?程式執行出來的結果卻是,
sizeof(ABC) = 16
sizeof(DEF) = 8
3. 這就是compiler為我們做了對齊的最佳化,將這二個的struct都調整成2的次方。
這樣有利於運算。

這樣的做法在PC上通常沒有問題,但若是在嵌入式系統上,記憶體必需要錙珠必較時
,我們就必須要考量到使用struct所佔掉的記憶體空間,上次和Tick討論Linux kernel
裡的List結構時,遇到了這個問題。他告訴我可以使用__attribute__((packed));這個關鍵字,
它的作用在於叫compiler不要為我們做對齊的最佳化,因此,計算的結果就會如同我們所想的一樣了。
struct ABC {
int index;
char name[6];
int score;
} __attribute__((packed));;

struct DEF{
int att;
char name[3];
} __attribute__((packed));;

int main(void)
{
printf("sizeof(ABC) = %d\n", sizeof(struct ABC));
printf("sizeof(DEF) = %d\n", sizeof(struct DEF));
return 0;

}
這樣就會得到以下的結果了。
sizeof(ABC) = 14
sizeof(DEF) = 7

這裡沒有哪一種用法比較好的問題,端看在使用上的需求,
要運算速度快,就需要資料對齊。要節省記憶體的使用,就取消對齊。

C語言中資料結構(struct)的大小的更多相关文章

  1. 安卓初級教程(4):sqlite建立資料庫

    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ...

  2. 問題排查:DataGridView 資料行下拉選單,資料繫結階段顯示 DataGridViewComboBoxCell 值無效

    可能原因: 1.下拉選單的選項資料繫結晚於 DataGridView 的資料繫結 2.下拉選單的 DataPropertyName 屬性,比 DisplayMember.ValueMember 早賦值 ...

  3. .net批量上傳Csv檔資料應用程序開發總結

    應用環境:visual studio 2010開發工具,Database為Sql2008以上版本 最近在生產環境中需要開發一款應用程式,上傳電子檔(.csv)資料至Database 最初方案: 以tx ...

  4. Active Record: 資料庫遷移(Migration) (转)

    Active Record: 資料庫遷移(Migration) Programming today is a race between software engineers striving to b ...

  5. [心得] SQL Server Partition(表分區) 資料分佈探討

    最近在群裡有個朋友問了個問題是這樣的 用户表有一千多万行,主键是用户ID,我做了分区.但经常查询时,其它的表根据用户ID来关联,这样跨区查询,reads非常高.有什么好的处理办法?不分区的话,索引维护 ...

  6. [转]SQL Server 安全性概論與無法刪除資料庫使用者的解決辦法

    經常有人來問我特定 SQL Server 資料庫裡的使用者無法刪除的問題,這問題其實跟 SQL Server 的安全性架構有很大關係,解決這個問題當然還是瞭解觀念的重要性大於知道如何解決問題.除了講解 ...

  7. 資料視覺化:使用Python與JavaScript 简介和目录

    內容簡介 學習如何運用Python與JavaScript這組對超級強大的組合,處理手中的原始資料,建構出功能強大的互動式視覺化網站.在這一本以實務為主的書中,將告訴您如何善用Python和JavaSc ...

  8. C 語言中的編譯指示 (Pragma)

    編譯指示 #pragma 是用來告知編譯器某些特殊指示,例如不要輸出錯誤訊息,抑制警告訊息,或者加上記憶體漏洞檢查機制等.這些指示通常不是標準的 C 語言所具備的,而是各家編譯器廠商或開發者所制定的, ...

  9. SQL Server 2016 的「動態資料遮罩 (Dynamic Data Masking)」

    一些特別注重資訊安全.個人資料的公司或產業 (如: 金融.保險業),通常「測試用資料庫」的資料,會加上「遮蔽:去識別化」的功能,避免個資外洩.以往必須自己撰寫 SQL 語句或 Stored Proce ...

随机推荐

  1. 如何取消bootstrap浮动时的padding值

    在bootstrap框架中使用浮动时,可以对元素添加pull-left 或 pull-right 类来达到目的.但是框架会默认给该元素添加一个15px的左右padding. <div class ...

  2. c# .netframwork 4.0 调用 2.0时报错 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。

    “System.IO.FileLoadException”类型的未经处理的异常在 XXX.dll 中发生 其他信息: 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的 ...

  3. js 可迭代对象

    作用:可以简化使用循环语句初始化一个变量记录迭代位置的操作 function createIterator(iterms) { let i = 0 return { next() { let done ...

  4. Echart报 [MODULE_MISS]"echarts/config的错

    echarts插件的引入有两种方式 项目用到Echarts插件,时下比较流行的是模块化包引入,但是很悲催的是楼主用的是标签式引入,所以从官网copy来的代码总是报一个 [MODULE_MISS]&qu ...

  5. sql 根据身份证判断年龄是否小于18岁

    SELECT *, Age= datediff(yy,cast(case when substring(PersonalId,,) ') /*若第7位不是'1'或'2'则表示是15位身份证编码规则*/ ...

  6. perl升级后shutter程序无法运行的修复

    这个问题真的很无语,perl升级后一些依赖perl的aur包不能用了,需要rebuild,这样让系统稳定性何在-- 运行shutter错误信息: $ shutter Can't locate Gnom ...

  7. 转载:java面试题(一)

    1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...

  8. js调用浏览器

    定义和用法 open() 方法用于打开一个新的浏览器窗口或查找一个已命名的窗口. 语法 window.open(URL,name,specs,replace) 参数 说明 URL 可选.打开指定的页面 ...

  9. cocos2D-X call JNIHelper

    #ifndef _WIN32 JNIEnv *j = JniHelper::getEnv(); if (j == nullptr || j == NULL) {test += "JNIEnv ...

  10. shell 根据路径获取文件名和目录

    path=/dir1/dir2/dir3/test.txt echo ${path##*/} 获取文件名 test.txtecho ${path##*.} 获取后缀 txt #不带后缀的文件名temp ...