共用體容許您在相同的內存位置存儲不一樣的數據類型。您能夠定義一個帶有多成員的共用體,可是任什麼時候候只能有一個成員帶有值。共用體提供了一種使用相同的內存位置的有效方式。html
爲了定義共用體,您必須使用 union 語句,方式與定義結構體相似。union 語句定義了一個新的數據類型,帶有多個成員。union 語句的格式以下:編程
union [union tag] { member definition; member definition; ... member definition; } [one or more union variables];
union tag 是可選的,每一個 member definition 是標準的變量定義,好比 int i; 或者 float f; 或者其餘有效的變量定義。在共用體定義的末尾,最後一個分號以前,您能夠指定一個或多個共用體變量,這是可選的。下面定義一個名爲 Data 的共用體類型,有三個成員 i、f 和 str:編程語言
union Data { int i; float f; char str[20]; } data;
如今,Data 類型的變量能夠存儲一個整數、一個浮點數,或者一個字符串。這意味着一個變量(相同的內存位置)能夠存儲多個多種類型的數據。您能夠根據須要在一個共用體內使用任何內置的或者用戶自定義的數據類型。函數
共用體佔用的內存應足夠存儲共用體中最大的成員。例如,在上面的實例中,Data 將佔用 20 個字節的內存空間,由於在各個成員中,字符串所佔用的空間是最大的。下面的實例將顯示上面的共用體佔用的總內存大小:this
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; printf( "Memory size occupied by data : %d\n", sizeof(data)); return 0; }
當上面的代碼被編譯和執行時,它會產生下列結果:命令行
Memory size occupied by data : 20指針
爲了訪問共用體的成員,咱們使用成員訪問運算符(.)。成員訪問運算符是共用體變量名稱和咱們要訪問的共用體成員之間的一個句號。您可使用 union 關鍵字來定義共用體類型的變量。code
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; data.i = 10; data.f = 220.5; strcpy( data.str, "C Programming"); printf( "data.i : %d\n", data.i); printf( "data.f : %f\n", data.f); printf( "data.str : %s\n", data.str); return 0; }
當上面的代碼被編譯和執行時,它會產生下列結果:orm
data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programminghtm
在這裏,咱們能夠看到共用體的 i 和 f 成員的值有損壞,由於最後賦給變量的值佔用了內存位置,這也是 str 成員可以無缺輸出的緣由。如今讓咱們再來看一個相同的實例,此次咱們在同一時間只使用一個變量,這也演示了使用共用體的主要目的:
#include <stdio.h> #include <string.h> union Data { int i; float f; char str[20]; }; int main( ) { union Data data; data.i = 10; printf( "data.i : %d\n", data.i); data.f = 220.5; printf( "data.f : %f\n", data.f); strcpy( data.str, "C Programming"); printf( "data.str : %s\n", data.str); return 0; }
當上面的代碼被編譯和執行時,它會產生下列結果:
data.i : 10
data.f : 220.500000
data.str : C Programming
在這裏,全部的成員都能無缺輸出,由於同一時間只用到一個成員。
typedef 關鍵字,您可使用它來爲類型取一個新的名字。下面的實例爲單字節數字定義了一個術語 BYTE:
typedef unsigned char BYTE;
在這個類型定義以後,標識符 BYTE 可做爲類型 unsigned char 的縮寫,例如:
BYTE b1, b2;
按照慣例,定義時會大寫字母,以便提醒用戶類型名稱是一個象徵性的縮寫,但您也可使用小寫字母。
您也可使用 typedef 來爲用戶自定義的數據類型取一個新的名字。例如,您能夠對結構體使用 typedef 來定義一個新的數據類型名字,而後使用這個新的數據類型來直接定義結構變量,以下:
#include <stdio.h> #include <string.h> typedef struct Books { char title[50]; char author[50]; char subject[100]; int book_id; } Book; int main( ) { Book book; strcpy( book.title, "C 教程"); strcpy( book.author, "Runoob"); strcpy( book.subject, "編程語言"); book.book_id = 12345; printf( "書標題 : %s\n", book.title); printf( "書做者 : %s\n", book.author); printf( "書類目 : %s\n", book.subject); printf( "書 ID : %d\n", book.book_id); return 0; }
當上面的代碼被編譯和執行時,它會產生下列結果:
書標題 : C 教程
書做者 : Runoob
書類目 : 編程語言
書 ID : 12345
#define 是 C 指令,用於爲各類數據類型定義別名,與 typedef 相似,可是它們有如下幾點不一樣:
下面是 #define 的最簡單的用法:
#include <stdio.h> #define TRUE 1 #define FALSE 0 int main( ) { printf( "TRUE 的值: %d\n", TRUE); printf( "FALSE 的值: %d\n", FALSE); return 0; }
當上面的代碼被編譯和執行時,它會產生下列結果:
TRUE 的值: 1
FALSE 的值: 0
當咱們提到輸入時,這意味着要向程序填充一些數據。輸入能夠是以文件的形式或從命令行中進行。C 語言提供了一系列內置的函數來讀取給定的輸入,並根據須要填充到程序中。
當咱們提到輸出時,這意味着要在屏幕上、打印機上或任意文件中顯示一些數據。C 語言提供了一系列內置的函數來輸出數據到計算機屏幕上和保存數據到文本文件或二進制文件中。
C 語言把全部的設備都看成文件。因此設備(好比顯示器)被處理的方式與文件相同。如下三個文件會在程序執行時自動打開,以便訪問鍵盤和屏幕。
標準文件 | 文件指針 | 設備 |
---|---|---|
標準輸入 | stdin | 鍵盤 |
標準輸出 | stdout | 屏幕 |
標準錯誤 | stderr | 您的屏幕 |
文件指針是訪問文件的方式,本節將講解如何從屏幕讀取值以及如何把結果輸出到屏幕上。
C 語言中的 I/O (輸入/輸出) 一般使用 printf() 和 scanf() 兩個函數。
scanf() 函數用於從標準輸入(鍵盤)讀取並格式化, printf() 函數發送格式化輸出到標準輸出(屏幕)。
#include <stdio.h> // 執行 printf() 函數須要該庫 int main() { printf("c語言教程"); //顯示引號中的內容 return 0; }
編譯以上程序,輸出結果爲:
c語言教程
實例解析:
%d 格式化輸出整數
#include <stdio.h> int main() { int testInteger = 5; printf("Number = %d", testInteger); return 0; }
編譯以上程序,輸出結果爲:
Number = 5
在 printf() 函數的引號中使用 "%d" (整型) 來匹配整型變量 testInteger 並輸出到屏幕。
%f 格式化輸出浮點型數據
#include <stdio.h> int main() { float f; printf("Enter a number: "); // %f 匹配浮點型數據 scanf("%f",&f); printf("Value = %f", f); return 0; }
int getchar(void) 函數從屏幕讀取下一個可用的字符,並把它返回爲一個整數。這個函數在同一個時間內只會讀取一個單一的字符。您能夠在循環內使用這個方法,以便從屏幕上讀取多個字符。
int putchar(int c) 函數把字符輸出到屏幕上,並返回相同的字符。這個函數在同一個時間內只會輸出一個單一的字符。您能夠在循環內使用這個方法,以便在屏幕上輸出多個字符。
請看下面的實例:
#include <stdio.h> int main( ) { int c; printf( "Enter a value :"); c = getchar( ); printf( "\nYou entered: "); putchar( c ); printf( "\n"); return 0; }
當上面的代碼被編譯和執行時,它會等待您輸入一些文本,當您輸入一個文本並按下回車鍵時,程序會繼續並只會讀取一個單一的字符,顯示以下:
$./a.out
Enter a value :runoobYou entered: r
char *gets(char *s) 函數從 stdin(鍵盤) 讀取一行到 s 所指向的緩衝區,直到一個終止符或 EOF。
int puts(const char *s) 函數把字符串 s 和一個尾隨的換行符寫入到 stdout(屏幕)。
#include <stdio.h> int main( ) { char str[100]; printf( "Enter a value :"); gets( str ); printf( "\nYou entered: "); puts( str ); return 0; }
當上面的代碼被編譯和執行時,它會等待您輸入一些文本,當您輸入一個文本並按下回車鍵時,程序會繼續並讀取一整行直到該行結束,顯示以下:
$./a.out
Enter a value :runoobYou entered: runoob
int scanf(const char *format, ...) 函數從標準輸入流 stdin 讀取輸入,並根據提供的 format 來瀏覽輸入。
int printf(const char *format, ...) 函數把輸出寫入到標準輸出流 stdout ,並根據提供的格式產生輸出。
format 能夠是一個簡單的常量字符串,可是您能夠分別指定 %s、%d、%c、%f 等來輸出或讀取字符串、整數、字符或浮點數。還有許多其餘可用的格式選項,能夠根據須要使用。經過下面這個簡單的實例來加深理解:
#include <stdio.h> int main( ) { char str[100]; int i; printf( "Enter a value :"); scanf("%s %d", str, &i); printf( "\nYou entered: %s %d ", str, i); printf("\n"); return 0; }
當上面的代碼被編譯和執行時,它會等待您輸入一些文本,當您輸入一個文本並按下回車鍵時,程序會繼續並讀取輸入,顯示以下:
$./a.out
Enter a value :runoob 123You entered: runoob 123
在這裏,應當指出的是,scanf() 期待輸入的格式與您給出的 %s 和 %d 相同,這意味着您必須提供有效的輸入,好比 "string integer",若是您提供的是 "string string" 或 "integer integer",它會被認爲是錯誤的輸入。另外,在讀取字符串時,只要遇到一個空格,scanf() 就會中止讀取,因此 "this is test" 對 scanf() 來講是三個字符串。