由淺至深->C語言中union和enum關鍵字的經典問題分析
引言:由淺至深系列的第二篇文章,繼續體悟語言中的一些細節!
文章嚮導
union的自我介紹
union與系統大小端
enum列舉的引入
真正意義上的常量?
正文
一、union的自我介紹
union(聯合/共用體)在語法描述上與struct有相似之處,是一種能在同一儲存空間記憶體儲不同型別資料的資料型別,換句話說,它主要被用於儲存某種既沒有規律、事先也未知順序的混合型別資料。
二、union與系統大小端
1.不可不知的union特性
為了更好地理解union使用上的特性,將其與struct進行一番對比:
struct A
{
int i;
char c;
};
union B
{
int i;
char c;
}
printf("%d\n", sizeof(struct A)); //輸出5
printf("%d\n", sizeof(union B)); //輸出4
上述並不是一份嚴格意義上的程式,但我們可從中得出一個結論:與struct不同,union只分配最大成員空間,且所有成員共享這一空間。既然是共享同一份空間,也就是可理解為共用同一個記憶體首地址,同時共用體中的成員都可以對這份空間進行操作,操作也是共同生效。關於操作共同生效這一點的體悟,將在接下來的系統大小端中詳細論述。
2.探祕系統大小端
在引出系統大小端這個問題前,我們不妨思考下述這樣一個情景:
union C
{
int i;
char c;
}
union C c;
c.i = 1;
printf("%d\n", c.c); //輸出值為多少?
或許有讀者會認為顯然結果為1嘛,但令人遺憾的是這個答案並不是那麼的令人滿意,why? 因為這個輸出值取決於系統的大小端模式,所以為了見到union的真正面貌,首先得打倒他的嘍囉“大小端”呢!
- 小端模式:低地址儲存低位資料
- 大端模式:低地址儲存高位資料
顯然,小端模式更符合人們直觀的思維對應關係,有點懵?看看下面的圖吧:
上述程式片段中,已將c.i賦值為1,它在記憶體空間中的儲存方式就如上圖描述的兩種情形。若為小端模式:因c.c為char型,則取到是該空間中的第一個位元組資料,故輸出為1;若為大端模式:同理可得,輸出為0。
3.實用程式(如何檢測系統大小端)
#include <stdio.h>
/* 檢查處理器大小端
* 若為大端模式,返回0
* 若為小端模式,返回1
*/
int checkCPU()
{
union w
{
int a;
char b;
}c;
c.a = 1;
return (c.b == 1); //判斷c.b是否與1相等,小端模式下低地址中存放的是0x01,而大端模式下高地址存放的是0x01
}
int main()
{
printf("%d\n", checkCPU());
return 0;
}
本程式就是基於系統大小端的原理進行編寫,讀者可好好體悟一番。
三、enum列舉的引入
enum是C語言的一種自定義型別,可用它建立一個新“型別”並指定其具有的值。將列舉引入的目的實際是為了提高程式的可讀性,舉個栗子:
enum color
{
RED;
BLUE = 2;
GREEN;
};
int main
{
int c = GREEN;
printf("%d\n", c); //輸出3
c = RED;
printf("%d\n", c); //輸出0
return 0;
}
上面這個例子雖然簡單,可卻向我們闡明瞭幾分道理:
- enum變數的型別實際上為int型
- 列舉中第一個定義的值預設為0(手動指定除外)
- 預設情況下後續定義的值為在前一個的基礎上+1
四、真正意義上的常量?
C語言中常量這個問題經常會在筆試/面試題中提及,或許首先映入你的腦海中會是const、define這兩個關鍵字,如果是,今天不妨重新認識它—enum !
- 首先,我const鄭重宣告,C語言中我沒法定義一個常量,很抱歉迷惑了一些初學者!如果你想得到一個只讀變數,我很樂意。
- emm,我define是可以定義一種稱之為巨集常量的東西,但我的本質是字面量(並不佔用記憶體空間),僅僅是在預編譯期進行文字替換而已。
- 今天我就把話撂在這兒:我enum可以定義C語言中真正意義上的常量!不信?非要我露一手你才信服:
#include<stdio.h>
enum //無名列舉,用於定義常量
{
SIZE = 10
};
void InitArray(int array[])
{
int i = 0;
for(i=0; i<SIZE; i++) //here!
{
array[i] = i+1;
}
}
void PrintArray(int array[])
{
int i = 0;
for(i=0; i<SIZE; i++) //here!
{
printf("%d\n",array[i]);
}
}
int main()
{
int array[SIZE]={0}; //here!
InitArray(array);
PrintArray(array);
return 0;
}
嗯,希望我說明白了。Farewell,my friend!
參閱資料
C Primer Plus
狄泰軟體學院-C語言進階剖析教程
相關推薦
由淺至深->C語言中union和enum關鍵字的經典問題分析
引言:由淺至深系列的第二篇文章,繼續體悟語言中的一些細節! 文章嚮導 union的自我介紹 union與系統大小端 enum列舉的引入 真正意義上的常量? 正文 一、union的自我介紹 union(聯合/共用體)在語
關於c語言中malloc和remalloc函式的分析
首先申明,這是本人第一次寫部落格,其目的僅僅是為了加強自己對知識點的掌握,為到達在本子上記筆記的效果 進入正題。對於malloc,它的作用就是為了動態分配空間,像c++中的new一樣。這裡就不說他們兩的區別了。malloc函式有這樣幾個特點。 1.分配的空間地址是連續的,
C語言中char*和char[]用法區別分析
本文例項分析了C語言中char* 和 char []的區別。分享給大家供大家參考之用。具體分析如下: 一般來說,很多人會覺得這兩個定義效果一樣,其實差別很大。以下是個人的一些看法,有不正確的地方望指正。 本質上來說,char *s定義了一個char型的指標,它只知道所指向的
【由淺至深】redis 現實發布訂閱的幾種方式
前言 提到訊息佇列,最熟悉無疑是 rabbitmq,它基本是業界標準的解決方案。本文詳細介紹 redis 多種現實輕訂閱方法,作者認為非常有趣並加以總結,希望對有需要的朋友學習 redis 功能有一定的帶入作用。 方法一:SUBSCRIBE + PUBLISH //程式1:使用程式碼現實訂閱端 var s
【MySQL經典案例分析】關於資料行溢位由淺至深的探討
本文由雲+社群發表 一、從常見的報錯說起 故事的開頭我們先來看一個常見的sql報錯資訊: 相信對於這類報錯大家一定遇到過很多次了,特別對於OMG這種已內容生產為主要工作核心的BG,在內容線的儲存中,資料大一定是個繞不開的話題。這裡的資料“大”,遠不止儲存空間佔用多,其中也包括了單個
【MySQL經典案例分析】關於數據行溢出由淺至深的探討
發布 解決 del set cloud 這樣的 自己 表結構 innodb 本文由雲+社區發表 一、從常見的報錯說起 ? 故事的開頭我們先來看一個常見的sql報錯信息: ? 相信對於這類報錯大家一定遇到過很多次了,特別對於OMG這種已內容生產為主要工作核心的BG,在內
c語言中fscanf和fprintf
寫的權限 set per efi errno fclose pri form price 很多時候我們需要寫入數據到文件中時都覺得很困擾,因為格式亂七八槽的,可讀性太差了,於是我們就想有沒有什麽函數可以格式化的從文件中輸入和輸出呢,還真有。下面我將講解一下fscanf和fp
C語言中typedef和sizeof的註意事項
isp sizeof spa 註意 list數據 對象 audio 應該 user typedef的作用是給一個數據類型起一個別名。 typedef struct LIST { int data; }SeqList; SeqList 就相當於struct LIS
c語言中external,static關鍵字用法
static用法: 在C中,static主要定義全域性靜態變數、定義區域性靜態變數、定義靜態函式。 1、定義全域性靜態變數:在全域性變數前面加上關鍵字static,該全域性變數變成了全域性靜態變數。全域性靜態變數有以下特點。 a.在全域性區分配記憶體。 b.如果沒有初始化,其預設值為
(C語言中printf函式讀取的具體分析)
(C語言中printf函式讀取的具體分析) 不多說,直接上。printf函式將傳入的資料傳送到記憶體堆區(緩衝區),然後再根據前面的(格式說明符一個個讀取,這樣會造成錯誤) #include<stdio.h> #include<limits.h> #incl
C語言中 malloc 和 free
from:http://blog.sina.com.cn/s/blog_af1a77fa0102xceb.html 一、malloc()和free()的基本概念以及基本用法: 1、函式原型及說明: void *malloc(long NumBytes):該函式分配了NumBytes個位元
c語言中static和auto的區別
1、static變數存放在靜態儲存區,在程式整個執行期間都不釋放;而auto變數存放在動態儲存區,隨著生命週期的結束而立即釋放。 2、static變數只賦值一次,以後就不用賦值;而auto變數在函式每呼叫一次都要賦初值
關於C語言中“x++”和“++x”的問題
關於一個變數在不同環境下自增自減的問題。 #include<stdio.h> int main() { int x = 8; int y = 0; y = (++x) + (x++) + (++x); printf("%d\n",y);
C語言中printf和scanf函式基本的引數型別和輸出形式
printf函式的引數型別和輸出形式 字元 引數型別 輸出形式 d,i int 十進位制數 o int 無符號八進位制數(不含前導0) x,X int 無符號十六進位制數(沒有前
C語言中“指標”和“指標變數”的區別是什麼
比較嚴格的說法是這樣的:系統為每一個記憶體單元分配一個地址值,C/C++把這個地址值稱為“指標”。如有int i=5;,存放變數i的記憶體單元的編號(地址)&i被稱為指標。“指標變數”則是存放前述“地址值”的變數,也可以表述為,“指標變數”是存放變數所佔記憶體空間“
C語言中i++和++i的區別
C語言中i++和++i的區別 C語言中++i和i++是有區別的!快速理解的話就是用一句話概括: 1、i++是先賦值再運算+1; 2、++i是先運算+1再賦值; i++和++i都是c語言裡的自增,但是它們自增的順序不同。++i表示,i自增1後再參與其它運算,而i++ 則是i參與運算後,i的
C語言中char * 和 char []的區別
問題引入: 在實習過程中發現了一個以前一直預設的錯誤,同樣char *c = "abc"和char c[]="abc",前者改變其內容程式是會崩潰的,而後者完全正確。 程式演示: #include <iostream> usingnamespa
C語言中的32個關鍵字及部分講解
說起c語言中的關鍵字,大家印象最深的可能就是int,double等定義一個數據變數時所使用的關鍵字了。但是除了這些資料型別的關鍵字還有哪些呢?for?while?沒錯,這些確實都是,但是並沒有一個系統的總結。本文筆者就將就c語言學習中所遇到的共計32個關鍵字進行整理。請善用搜
C語言中const和C++中const關鍵字的區別
# include "iostream" using namespace std; struct Teacher { char name[30]; int age; }; void operatorTeacher(Teacher *pT) {
C語言中typedef和define的區別
正確思考typedef和巨集文字替換直接的區別關鍵在於就是把typedef看成一種徹底的“封裝”型別——在宣告它之後不能在裡面增加別的東西。它和巨集的區別主要體現在兩個方面。 一、可以用其他型別說明符對巨集型別名進行擴充套件,但對typedef所定義的型別名卻不