今天咱們繼續來學習C語言的入門知識點程序員
任何一種編程中,做用域是程序中定義的變量所存在的區域,超過該區域變量就不能被訪問。C 語言中有三個地方能夠聲明變量:spring
在函數或塊內部的局部變量編程
在全部函數外部的全局變量數組
在形式參數的函數參數定義中微信
讓咱們來看看什麼是局部變量、全局變量和形式參數。數據結構
局部變量dom
在某個函數或塊的內部聲明的變量稱爲局部變量。它們只能被該函數或該代碼塊內部的語句使用。局部變量在函數外部是不可知的。下面是使用局部變量的實例。在這裏,全部的變量 a、b 和 c 是 main() 函數的局部變量。編程語言
void main(){函數
//局部變量學習
int a, b;
int c;
//初始化局部變量
a = 10;
b = 20;
c = a + b;
//%d:以十進制形式輸出帶符號整數(正數不輸出符號)
printf("values of a = %d,b = %d and c = %d \n", a, b, c);
}
輸出:values of a = 10,b = 20 and c = 30
全局變量
全局變量是定義在函數外部,一般是在程序的頂部。全局變量在整個程序生命週期內都是有效的,在任意的函數內部能訪問全局變量。
全局變量能夠被任何函數訪問。也就是說,全局變量在聲明後整個程序中都是可用的。下面是使用全局變量和局部變量的實例:
//全局變量聲明
int g;
void main(){
int a, b;
//初始化局部變量
a = 10;
b = 20;
//所有變量賦值
g = a + c;
printf("values of a = %d,bc = %d and g = %d \n", a, c, g);
}
輸出:values of a = 10,bc = 30 and g = 40
形式參數
函數的參數,形式參數,被看成該函數內的局部變量,若是與全局變量同名它們會優先使用。下面是一個實例:
int sumA(int a, int b) {
printf("value of a in sum() = %d\n", a);
printf("value of b in sum() = %d\n", b);
return x + y;
}
void main(){
int a, b,c;
//初始化局部變量
a = 10;
b = 20;
c = sumA(a, b);
printf("value of c in main() = %d\n", c);
}
輸出:value of a in main() = 30
全局變量和局部變量的區別
(1)全局變量保存在內存的全局存儲區中,佔用靜態的存儲單元;
(2)局部變量保存在棧中,只有在所在函數被調用時才動態地爲變量分配存儲單元。
初始化局部變量和全局變量的默認值
C 語言支持數組數據結構,它能夠存儲一個固定大小的相同類型元素的順序集合。數組是用來存儲一系列數據,但它每每被認爲是一系列相同類型的變量。
數組的聲明並非聲明一個個單獨的變量,好比 number0、number一、...、number99,而是聲明一個數組變量,好比 numbers,而後使用 numbers[0]、numbers[1]、...、numbers[99] 來表明一個個單獨的變量。數組中的特定元素能夠經過索引訪問。
全部的數組都是由連續的內存位置組成。最低的地址對應第一個元素,最高的地址對應最後一個元素。
聲明數組
在 C 中要聲明一個數組,須要指定元素的類型和元素的數量,以下所示:
type arrayName [ arraySize ];
這叫作一維數組。arraySize 必須是一個大於零的整數常量,type 能夠是任意有效的 C 數據類型。例如,要聲明一個類型爲 double 的包含 10 個元素的數組 balance,聲明語句以下:
double balance[10];
初始化數組
void main(){
double balance[10] = {1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0}
}
大括號 { } 之間的值的數目不能大於咱們在數組聲明時在方括號 [ ] 中指定的元素數目。
若是您省略掉了數組的大小,數組的大小則爲初始化時元素的個數。所以,若是:
void main(){
double balance[] = {1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0}
}
您將建立一個數組,它與前一個實例中所建立的數組是徹底相同的。下面是一個爲數組中某個元素賦值的實例:
balance[1] = 50.5;
訪問數組元素
//跟 Java 同樣
double value = balance[1]
例子:
void main() {
//定義一個長度爲 10 的整數數組
int n[10];
int i, j;
//初始化數組元素
for (i = 0; i < 10; i++) {
n[i] = 2 * i;
}
//輸出元素中的數據
for (int k = 0; k < 10; ++k) {
printf("Element[%d] = %d \n", k, n[k]);
}
//總的大小除以其中一個大小就獲得了 數組長度
printf("整數數組 n 的長度: %d \n", sizeof(n) / sizeof(n[0]));
//輸出元素中的數據
for (int k = 0; k < sizeof(n) / sizeof(n[0]); ++k) {
printf("Element[%d] = %d \n", k, n[k]);
}
}
輸出:
Element[0] = 0
Element[1] = 2
Element[2] = 4
Element[3] = 6
Element[4] = 8
Element[5] = 10
Element[6] = 12
Element[7] = 14
Element[8] = 16
Element[9] = 18
整數數組 n 的長度: 10
Element[0] = 0
Element[1] = 2
Element[2] = 4
Element[3] = 6
Element[4] = 8
Element[5] = 10
Element[6] = 12
Element[7] = 14
Element[8] = 16
Element[9] = 18
C 中數組詳解
在 C 中,數組是很是重要的,咱們須要瞭解更多有關數組的細節。下面列出了 C 程序員必須清楚的一些與數組相關的重要概念:
枚舉是 C 語言中的一種基本數據類型,它可讓數據更簡潔,更易讀。
枚舉語法定義格式爲:
enum 枚舉名 {枚舉元素1,枚舉元素2,……};
接下來咱們舉個例子,好比:一星期有 7 天,若是不用枚舉,咱們須要使用 #define 來爲每一個整數定義一個別名:
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
這個看起來代碼量就比較多,接下來咱們看看使用枚舉的方式:
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
這樣看起來是否是更簡潔了。
**注意:**第一個枚舉成員的默認值爲整型的 0,後續枚舉成員的值在前一個成員上加 1。咱們在這個實例中把第一個枚舉成員的值定義爲 1,第二個就爲 2,以此類推。
能夠在定義枚舉類型時改變枚舉元素的值:
enum season {spring, summer=3, autumn, winter};
沒有指定值的枚舉元素,其值爲前一元素加 1。也就說 spring 的值爲 0,summer 的值爲 3,autumn 的值爲 4,winter 的值爲 5
枚舉變量的定義
前面咱們只是聲明瞭枚舉類型,接下來咱們看看如何定義枚舉變量。
咱們能夠經過如下三種方式來定義枚舉變量
一、先定義枚舉類型,再定義枚舉變量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
二、定義枚舉類型的同時定義枚舉變量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
三、省略枚舉名稱,直接定義枚舉變量
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
學習 C 語言的指針既簡單又有趣。經過指針,能夠簡化一些 C 編程任務的執行,還有一些任務,如動態內存分配,沒有指針是沒法執行的。因此,想要成爲一名優秀的 C 程序員,學習指針是頗有必要的。
正如您所知道的,每個變量都有一個內存位置,每個內存位置都定義了可以使用連字號(&)運算符訪問的地址,它表示了在內存中的一個地址。請看下面的實例,它將輸出定義的變量地址:
void main(){
int var1;
char var2[10];
//%p : 輸出指針地址
printf("var1 變量的地址:%p \n", &var1);
printf("var2 變量的地址:%p \n", &var2);
}
輸出:
var1 變量的地址:0x7ffee7e976b8
var2 變量的地址:0x7ffee7e976be
經過上面的實例,咱們瞭解了什麼是內存地址以及如何訪問它。接下來讓咱們看看什麼是指針。
什麼是指針?
指針是一個變量,其值爲另外一個變量的地址,即內存位置的直接地址。就像其餘變量或常量同樣,您必須在使用指針存儲其餘變量地址以前,對其進行聲明。指針變量聲明的通常形式爲:
type *var-name
在這裏,type 是指針的基類型,它必須是一個有效的 C 數據類型,var-name 是指針變量的名稱。用來聲明指針的星號 * 與乘法中使用的星號是相同的。可是,在這個語句中,星號是用來指定一個變量是指針。如下是有效的指針聲明:
int *i; //一個整型的指針
double *d;//double 型指針
float *f;//浮點型指針
char *ch//字符型指針
全部實際數據類型,不論是整型、浮點型、字符型,仍是其餘的數據類型,對應指針的值的類型都是同樣的,都是一個表明內存地址的長的十六進制數。
不一樣數據類型的指針之間惟一的不一樣是,指針所指向的變量或常量的數據類型不一樣。
如何使用指針?
使用指針時會頻繁進行如下幾個操做:定義一個指針變量、把變量地址賦值給指針、訪問指針變量中可用地址的值。這些是經過使用一元運算符 ***** 來返回位於操做數所指定地址的變量的值。下面的實例涉及到了這些操做:
例子:
//如何使用指針
int var = 66;//實際變量的聲明
int *ip;//指針變量的聲明
ip = &var; //指針變量中存儲 var 的地址
printf("var 的地址 : %p \n", var);
//在指針變量中存儲的地址
printf("ip 的地址:%p \n", ip);
//使用指針訪問地址
printf("ip 指針對應的地址:%p \n", *ip);
//使用指針訪問地址對應的值
printf("ip 指針對應的地址:%d \n", *ip);
輸出:
var 的地址 : 0x42
ip 的地址:0x7ffee96eb6b4
ip 指針對應的地址:0x42
ip 指針對應的地址:66
C 中的 NULL 指針
在變量聲明的時候,若是沒有確切的地址能夠賦值,爲指針變量賦一個 NULL 值是一個良好的編程習慣。賦爲 NULL 值的指針被稱爲空指針。
NULL 指針是一個定義在標準庫中的值爲零的常量。請看下面的程序:
void main(){
//賦值一個 NULL 指針
int *ptr = NULL;
printf("ptr 的地址是: %p \n", ptr);
//檢查一個空指針
if (ptr) printf("若是 ptr 不是空指針,則執行"); else printf("若是 ptr 是空指針,則執行");
}
輸出:ptr 的地址是: 0x0 ptr 是空指針
C 指針詳解
在 C 中,有不少指針相關的概念,這些概念都很簡單,可是都很重要。下面列出了 C 程序員必須清楚的一些與指針相關的重要概念:
函數指針是指向函數的指針變量。
一般咱們說的指針變量是指向一個整型、字符型或數組等變量,而函數指針是指向函數。
函數指針能夠像通常函數同樣,用於調用函數、傳遞參數。
函數指針變量的聲明:
typedef int (*fun_ptr)(int,int)//聲明一個指向一樣參數,返回值得函數指針類型
回調函數
函數指針變量能夠做爲某個函數的參數來使用的,回調函數就是一個經過函數指針調用的函數。
簡單講:回調函數是由別人的函數執行時調用你實現的函數。
例子:
例子中 populate_array 函數定義了三個參數,其中第三個參數是函數的指針,經過該函數來設置數組的值。
實例中咱們定義了回調函數 getNextRandomValue,它返回一個隨機值,它做爲一個函數指針傳遞給 populate_array 函數。
populate_array 將調用 10 次回調函數,並將回調函數的返回值賦值給數組。
#include <stdlib.h>
#include <stdio.h>
//回調函數
void populate_array(int *array, size_t arraySize, int(*getNextValue)(void)) {
printf("array 地址:%p \n", array);
for (size_t i = 0; i < arraySize; i++) {
array[i] = getNextValue();
printf(" array[%d] ,存儲值:%d \n", i, array[i]);
}
}
//獲取一個隨機數
int getNextRandomValue(void) {
return rand();
}
void main() {
//回調函數
int array[10];
printf("Int array 地址:%p \n", array);
populate_array(array, sizeof(array)/sizeof(array[0]), getNextRandomValue);
for (int i = 0; i < sizeof(array)/sizeof(array[0]); ++i) {
printf(" array[%d] , 對應值爲:%d \n", i, array[i]);
}
}
輸出:
Int array 地址:0x7ffeebf1a650
array 地址:0x7ffeebf1a650
array[0] ,存儲值:16807
array[1] ,存儲值:282475249
array[2] ,存儲值:1622650073
array[3] ,存儲值:984943658
array[4] ,存儲值:1144108930
array[5] ,存儲值:470211272
array[6] ,存儲值:101027544
array[7] ,存儲值:1457850878
array[8] ,存儲值:1458777923
array[9] ,存儲值:2007237709
array[0] , 對應值爲:16807
array[1] , 對應值爲:282475249
array[2] , 對應值爲:1622650073
array[3] , 對應值爲:984943658
array[4] , 對應值爲:1144108930
array[5] , 對應值爲:470211272
array[6] , 對應值爲:101027544
array[7] , 對應值爲:1457850878
array[8] , 對應值爲:1458777923
array[9] , 對應值爲:2007237709
在 C 語言中,字符串其實是使用null字符 '\0' 終止的一維字符數組。所以,一個以 null 結尾的字符串,包含了組成字符串的字符。
下面的聲明和初始化建立了一個 "Hello" 字符串。因爲在數組的末尾存儲了空字符,因此字符數組的大小比單詞 "Hello" 的字符數多一個。
char ch[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
也可使用如下簡寫模式:
char ch[6] = "Hello"
字符串在 C/C++ 中內存表示:
其實,您不須要把 null 字符放在字符串常量的末尾。C 編譯器會在初始化數組時,自動把 '\0' 放在字符串的末尾。讓咱們嘗試輸出上面的字符串:
void main(){
//定義一個 char 數組
char string[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
//簡寫
char string2[6] = "Hello";
//%s:輸出字符串
printf("string message : %s\n", string);
}
輸出:string message : Hello
C 中對字符串操做的 API
C 數組容許定義可存儲相同類型數據項的變量,結構是 C 編程中另外一種用戶自定義的可用的數據類型,它容許您存儲不一樣類型的數據項。
結構用於表示一條記錄,假設您想要跟蹤圖書館中書本的動態,您可能須要跟蹤每本書的下列屬性:
(1)Title
(2)Author
(3)Subject
(4)Book ID
定義結構
爲了定義結構,您必須使用struct語句。struct 語句定義了一個包含多個成員的新的數據類型,struct 語句的格式以下:
struct name{
member-list;
member-list;
...
}name_tag,
name是結構的標籤。
member-list是標準的變量定義,好比 int i;或者 float f,或者其它有效的變量定義。
name_tag結構變量,定義在結構的末尾,最後一個分號以前,你能夠指定一個或多個結構變量,下面是聲明 Book 的結構方式:
struct Books{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
注意:在定義結構體的時候name、member-list、name_tag 這 3 部分至少要出現 2 個。
結構體變量的初始化
和其它類型變量同樣,在初始化的時候能夠指定初始值。
//定義一個 Books 結構,相似於 Java 中的數據 bean
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
double rmb;
} book = {"Java", "Android", "C 語言", 666, 55.5};
void main(){
//打印 Books
printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\nrmb: %f\n", book.title,
book.author, book.subject, book.book_id, book.rmb);
}
輸出:
title : Java
author: Android
subject: C 語言
book_id: 666
rmb: 55.500000
訪問結構成員
struct Books2 {
char title[50];
char author[50];
char subject[100];
int book_id;
};
void main(){
//訪問 Books2 結構成員
struct Books2 Books2A;//聲明 Books2A 類型爲 Books2
struct Books2 Books2B;//聲明 Books2B 類型爲 Books2
//Books2A 詳述
strcpy(Books2A.title, "C Plus");
strcpy(Books2A.author, "Nuha Ali");
strcpy(Books2A.subject, "C");
Books2A.book_id = 666888;
//Books2B 詳述
strcpy(Books2B.title, "C++ Plus");
strcpy(Books2B.author, "DevYK");
strcpy(Books2B.subject, "C++");
Books2B.book_id = 666999;
// 輸出 Book1 信息
printf("Book 1 title : %s\n", Books2A.title);
printf("Book 1 author : %s\n", Books2A.author);
printf("Book 1 subject : %s\n", Books2A.subject);
printf("Book 1 book_id : %d\n", Books2A.book_id);
// 輸出 Book2 信息
printf("Book 2 title : %s\n", Books2B.title);
printf("Book 2 author : %s\n", Books2B.author);
printf("Book 2 subject : %s\n", Books2B.subject);
printf("Book 2 book_id : %d\n", Books2B.book_id);
}
輸出:
Book 1 title : C Plus
Book 1 author : Nuha Ali
Book 1 subject : C
Book 1 book_id : 666888
Book 2 title : C++ Plus
Book 2 author : DevYK
Book 2 subject : C++
Book 2 book_id : 666999
結構做爲函數參數
//函數聲明
void printBook(struct Books2 books2);
void main(){
//訪問 Books2 結構成員
struct Books2 Books2A;//聲明 Books2A 類型爲 Books2
struct Books2 Books2B;//聲明 Books2B 類型爲 Books2
//Books2A 詳述 ,將 CPlus copy 到 title 中
strcpy(Books2A.title, "C Plus");
strcpy(Books2A.author, "Nuha Ali");
strcpy(Books2A.subject, "C");
Books2A.book_id = 666888;
//Books2B 詳述
strcpy(Books2B.title, "C++ Plus");
strcpy(Books2B.author, "DevYK");
strcpy(Books2B.subject, "C++");
Books2B.book_id = 666999;
// 輸出 Book1 信息
printf("Book 1 title : %s\n", Books2A.title);
printf("Book 1 author : %s\n", Books2A.author);
printf("Book 1 subject : %s\n", Books2A.subject);
printf("Book 1 book_id : %d\n", Books2A.book_id);
// 輸出 Book2 信息
printf("Book 2 title : %s\n", Books2B.title);
printf("Book 2 author : %s\n", Books2B.author);
printf("Book 2 subject : %s\n", Books2B.subject);
printf("Book 2 book_id : %d\n", Books2B.book_id);
printf("\n\n\n");
//結構做爲函數參數
printBook(Books2A);
printBook(Books2B);
}
void printBook(struct Books2 book) {
printf("Book title : %s\n", book.title);
printf("Book author : %s\n", book.author);
printf("Book subject : %s\n", book.subject);
printf("Book book_id : %d\n", book.book_id);
}
輸出:
Book 1 title : C Plus
Book 1 author : Nuha Ali
Book 1 subject : C
Book 1 book_id : 666888
Book 2 title : C++ Plus
Book 2 author : DevYK
Book 2 subject : C++
Book 2 book_id : 666999
Book title : C Plus
Book author : Nuha Ali
Book subject : C
Book book_id : 666888
Book title : C++ Plus
Book author : DevYK
Book subject : C++
Book book_id : 666999
指向結構的指針
您能夠定義指向結構的指針,方式與定義指向其餘類型變量的指針類似,以下所示:
struct Books *struct_pointer;
如今,您能夠在上述定義的指針變量中存儲結構變量的地址。爲了查找結構變量的地址,請把 & 運算符放在結構名稱的前面,以下所示:
struct_pointer = &Book1;
爲了使用指向該結構的指針訪問結構的成員,您必須使用 -> 運算符,以下所示:
struct_pointer->title;
例子:
//定義指向結構的指針
void printBookZZ(struct Books2 *books2);
void main(){
//訪問 Books2 結構成員
struct Books2 Books2A;//聲明 Books2A 類型爲 Books2
struct Books2 Books2B;//聲明 Books2B 類型爲 Books2
//Books2A 詳述 ,將 CPlus copy 到 title 中
strcpy(Books2A.title, "C Plus");
strcpy(Books2A.author, "Nuha Ali");
strcpy(Books2A.subject, "C");
Books2A.book_id = 666888;
//Books2B 詳述
strcpy(Books2B.title, "C++ Plus");
strcpy(Books2B.author, "DevYK");
strcpy(Books2B.subject, "C++");
Books2B.book_id = 666999;
//經過內存地址傳遞信息,爲了查找結構變量的地址,請把 & 運算符放在結構名稱的前面
printBookZZ(&Books2A);
printBookZZ(&Books2B);
}
/**
* 爲了使用指向該結構的指針訪問結構的成員,您必須使用 -> 運算符,以下所示:
* @param book
*/
void printBookZZ(struct Books2 *book) {
printf("Book -> title : %s\n", book->title);
printf("Book -> author : %s\n", book->author);
printf("Book -> subject : %s\n", book->subject);
printf("Book -> book_id : %d\n", book->book_id);
}
位域
有些信息在存儲時,並不須要佔用一個完整的字節,而只需佔幾個或一個二進制位。例如在存放一個開關量時,只有 0 和 1 兩種狀態,用 1 位二進位便可。爲了節省存儲空間,並使處理簡便,C 語言又提供了一種數據結構,稱爲"位域"或"位段"。
所謂"位域"是把一個字節中的二進位劃分爲幾個不一樣的區域,並說明每一個區域的位數。每一個域有一個域名,容許在程序中按域名進行操做。這樣就能夠把幾個不一樣的對象用一個字節的二進制位域來表示。
典型的實例:
(1)用 1 位二進位存放一個開關量時,只有 0 和 1 兩種狀態。
(2)讀取外部文件格式——能夠讀取非標準的文件格式。
位域ed 定義:
struct 位域結構名稱{
位域列表
};
位域列表的形式爲:類型說明符 位域名:位域長度
例:
struct bean {
int a:8;
int b:4;
int c:4;
}data;
說明 data 爲 bean 變量,共佔 2個字節。其中位域 a 佔 8 位,位域 b 佔 4 位,位域 c 佔 4 位。
注意:
一個位域存儲在同一個字節中,如一個字節所剩空間不夠存放另外一位域時,則會從下一單元起存放該位域。也能夠有意使某位域從下一單元開始。例如:
struct bean{
unsigned a:4;
unsigned :4;//空域
unsigned b:4;//從下一個單元開始存放
unsigned c:4;
}
在這個位域定義中共佔用 2 個字節,a 佔第一字節的 4 位,後 4 位填 0 表示不使用,b 從第二字節開始,佔用 4 位,c 佔用 4 位。
因爲位域不容許跨兩個字節,所以位域的長度不能大於一個字節的長度,也就是說不能超過8位二進位。若是最大長度大於計算機的整數字長,一些編譯器可能會容許域的內存重疊,另一些編譯器可能會把大於一個域的部分存儲在下一個字中。
位域能夠是無名位域,這時它只用來做填充或調整位置。無名的位域是不能使用的。例如:
struct k{
int a:1;
int :2; /* 該 2 位不能使用 */
int b:3;
int c:2;
};
從以上分析能夠看出,位域在本質上就是一種結構類型,不過其成員是按二進位分配的。
位域的使用
位域的使用和結構成員的使用相同,其通常形式爲:
(1)位域變量名.位域名
(2)位域變量名->位域名
位域容許用各類格式輸出。
共用體是一種特殊的數據類型,容許您在相同的內存位置存儲不一樣的數據類型。您能夠定義一個帶有多成員的共用體,可是任什麼時候候只能有一個成員帶有值。共用體提供了一種使用相同的內存位置的有效方式。
定義共同體
爲了定義共用體,您必須使用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 將佔用 20 個字節的內存空間,由於在各個成員中,字符串所佔用的空間是最大的。下面的實例將顯示上面的共用體佔用的總內存大小:
union Data {
int i;
float f;
char str[20];
};
void main(){
union Data data;
printf("Memory size occupied by data: %d\n", sizeof(data));
}
輸出:Memory size occupied by data: 20
訪問共同體成員
爲了訪問共用體的成員,咱們使用成員訪問運算符(.)。成員訪問運算符是共用體變量名稱和咱們要訪問的共用體成員之間的一個句號。您可使用 union 關鍵字來定義共用體類型的變量。下面的實例演示了共用體的用法:
union Data {
int i;
float f;
char str[20];
};
void main() {
//1. 訪問共同體 no
data.i = 10;
data.f = 1314.520;
strcpy(data.str,"C/C++");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);
printf("\n\n\n");
//2. 訪問共同體 yes
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 1314.520;
printf( "data.f : %f\n", data.f);
strcpy(data.str,"C/C++");
printf( "data.str : %s\n", data.str);
}
輸出:
data.i : 725823299
data.f : 0.000000
data.str : C/C++
data.i : 10
data.f : 1314.520020
data.str : C/C++
在這裏,咱們能夠看到上面註釋 1 共用體的 i 和 f 成員的值有損壞,由於最後賦給變量的值佔用了內存位置,這也是 str 成員可以無缺輸出的緣由。咱們看註釋 2 ,此次咱們在同一時間只使用一個變量成員,因此都能無缺輸出。
參考 17.(位域的介紹)
C 語言提供了 typedef 關鍵字,您可使用它來爲類型取一個新的名字。下面的實例爲單字節數字定義了一個術語 BYTE:
typedef unsigned char BYTE;
在這個類型定義以後,標識符 BYTE 可做爲類型 unsigned char 的縮寫,例如:
BYTE b1, b2;
按照慣例,定義時會大寫字母,以便提醒用戶類型名稱是一個象徵性的縮寫,但您也可使用小寫字母,以下:
typedef unsigned char byte;
您也可使用 typedef 來爲用戶自定義的數據類型取一個新的名字。例如,您能夠對結構體使用 typedef 來定義一個新的數據類型名字,而後使用這個新的數據類型來直接定義結構變量,以下:
typedef struct Books {
char title[50];
char author[50];
char subject[50];
int book_id;
} Book;
#define TRUE 1
#define FALSE 0
void 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);
printf( "TRUE 的值: %d\n", TRUE);
printf( "FALSE 的值: %d\n", FALSE);
}
輸出:
書標題 : C 教程
書做者 : Runoob
書類目 : 編程語言
書 ID : 12345
TRUE 的值: 1
FALSE 的值: 0
typedef vs define
define是 C 指令,用於爲各類數據類型定義別名,與typedef相似,可是它們有如下幾點不一樣:
(1)typedef僅限於爲類型定義符號名稱,#define不只能夠爲類型定義別名,也能爲數值定義別名,好比您能夠定義 1 爲 ONE。
(2)typedef是由編譯器執行解釋的,#define語句是由預編譯器進行處理的。
例子能夠參考上面是 #define 使用。
本節知識將會以分節的形式向你們展現,又想要學習C語言的小夥伴能夠關注筆者!一塊兒來加油呀~
自學C/C++編程難度很大,不妨和一些志同道合的小夥伴一塊兒學習成長!
C語言C++編程學習交流圈子,【點擊進入】微信公衆號:C語言編程學習基地
有一些源碼和資料分享,歡迎轉行也學習編程的夥伴,和你們一塊兒交流成長會比本身琢磨更快哦!