---------------------------------------------------------------------
枚舉:
// main.c #include <stdio.h> const int red = 0; const int yellow = 1; const int green = 2; int main(int argc, const char * argv[]) { /* 常量符號化:用符號而不是具體的數字來表示程序中的數字; 這樣看到符號才能知道背後的意思 */ int color = -1; char *colorName = NULL; printf("輸入顏色代碼:"); scanf("%d", &color); switch (color) { case red: colorName = "red"; break; case yellow: colorName = "yellow"; break; case green: colorName = "green"; break; default: colorName = "unknow"; break; } printf("顏色是:%s\n", colorName); return 0; }
// main.c #include <stdio.h> enum COLOR {RED, YELLOW, GREEN}; int main(int argc, const char * argv[]) { /* 枚舉:用枚舉而不是定義獨立的const int變量 */ int color = -1; char *colorName = NULL; printf("輸入顏色代碼:"); scanf("%d", &color); switch (color) { case RED: colorName = "red"; break; case YELLOW: colorName = "yellow"; break; case GREEN: colorName = "green"; break; default: colorName = "unknow"; break; } printf("顏色是:%s", colorName); return 0; }
// main.c #include <stdio.h> enum color {red, yellow, green}; //聲明數據類型color void f(enum color c); //f函數需要傳入叫color的枚舉類型 int main(int argc, const char * argv[]) { /* 枚舉是一種用戶定義的數據類型,用關鍵字enum以如下語法來聲明: enum 枚舉類型名字 {名字0, ..., 名字n}; 枚舉類型名字通常並不是真的使用,要用的實在大括號裡的名字,因為它們就是常量符號,它們的類型是int,值依次從0到n。如: enum colors {red, yellow, green}; 這樣就創建了三個常量,red的值是0,yellow是1,green是2。 當需要一些可以排列起來的常量值時,定義枚舉的意義就是給了這些常量值名字。 */ /* 枚舉量可以作為值 枚舉類型可以跟上enum作為類型 但是實際上是以整數來做內部計算和外部輸入輸出的 */ enum color t = red; //t是color的枚舉類型 scanf("%d", &t); f(t); return 0; } void f(enum color c) { printf("%d\n", c); }
// main.c
#include <stdio.h> enum COLOR {RED, YELLOW, GREEN, NumCOLORS}; int main(int argc, const char * argv[]) { /* 套路:自動計數的枚舉(如:NumCOLORS) 這樣需要遍歷所有的枚舉量或者需要建立一個用枚舉量做下標的數組的時候就很方便了 枚舉量:聲明枚舉量的時候可以指定值 enum COLOR {RED=1, YELLOW, GREEN = 5, NumCOLORS}; */ int color = -1; char *ColorNames[NumCOLORS] = { "red", "yellow", "green", }; char *colorName = NULL; printf("輸入顏色代碼:"); scanf("%d", &color); if (color >=0 && color < NumCOLORS) { colorName = ColorNames[color]; } else { colorName = "unknown"; } printf("顏色是:%s\n", colorName); /* 雖然枚舉類型可以當作類型使用,但是實際上很少用; 如果有意義上排比的名字,用枚舉比const int方便; 枚舉比宏(macro)好,因為枚舉有int類型。 */ return 0; }
結構:
// main.c // Created by weichen on 15/6/28. // Copyright (c) 2015年 weichen. All rights reserved.
#include <stdio.h> // 聲明一種新的結構類型,非實體;.運算符左邊的結構變量才是實體 struct date { int month; int day; int year; }; int main(int argc, const char * argv[]) { /*
- 結構類型 -
結構類型:復合數據類型, 成員變量可以是不同類型,聲明結構類型是一條語句,結尾需要分號。 1.和本地變量一樣,在函數內部聲明的結構類型只能在函數內部使用。 2.所以通常在函數外部聲明結構類型,這樣就可以被多個函數所使用了。 3.結構類型和結構變量是兩件事情,通過一種結構類型可以定義出很多結構變量,每個結構變量按照結構聲明的樣子具有相同的成員變量。 聲明結構的形式: 1. struct point { int x; int y; }; struct point p1,p2; // p1和p2都是point裡面有x和y的值(變量)。 2. struct { int x; int y; } p1, p2; // p1和p2都是一種無名結構,裡面有x和y;p1和p2並不是類型的名字,這裡只是想要兩個變量p1和p2,而且以後不想繼續使用這個結構,所以沒有起名字;做法不常見。 3. struct point { int x; int y; } p1, p2; // 聲明一個point結構,並定義兩個變量p1和p2,常見。 結構的初始化: struct date today = {07, 31, 2014}; //以數組的方式順序賦值 struct date thismonth = {.month=7, .year=2014}; //數組內以.成員變量的方式賦值,沒有賦值的為0 結構成員: 結構和數組有點像 數組的成員類型必須一樣,結構的成員類型可以不一樣 數組用[]運算符和下標訪問其成員,a[0] = 10; 結構用.運算符和名字訪問其成員,today.day; student.firstName; p1.x; p1.y; 結構運算: 要訪問整個結構,直接用結構變量的名字 對於整個結構,可以做賦值、取地址,也可以傳遞給函數參數 p1 = (struct point){5, 10}; //將5,10強制轉換為point結構的變量, 賦給p1,相當於p1.x = 5; p1.y = 10; p1 = p2; //相當於p1.x = p2.x; p1.y = p2.y; 數組變量在初始化後無法做這種賦值的運算 結構指針: 和數組不同,結構變量的名字並不是結構變量的地址,必須使用&運算符 struct date *pDate = &today; */ /* 定義一個結構的變量today(類型是struct date,下面就可以使用today) struct date today; today.month = 06; today.day = 28; today.year = 2015; */ struct date today = {06, 28, 2015}; struct date thismonth = {.month=6, .year=2015}; struct date t; //未賦值的結構變量 t = (struct date){06, 28, 2015}; //賦值 struct date m; m = t; //m和t是兩個不同的變量,賦值之後,m就得到了t所有成員的值 //m.year = 2016; 給m單獨賦值,不會改變t的值 struct date *pDate = &today; printf("Today's date is %i-%i-%i\n", today.year, today.month, today.day); //Today's date is 2015-6-28 printf("This month is %i-%i-%i\n", thismonth.year, thismonth.month, thismonth.day); //This month is 2015-6-0 printf("t is %i-%i-%i\n", t.year, t.month, t.day); //t is 2015-6-28 printf("m is %i-%i-%i\n", m.year, m.month, m.day); //m is 2015-6-28 printf("%p", &pDate); //0x7fff5fbff7d8 return 0; }
// main.c // Created by weichen on 15/6/29. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> struct point { int x; int y; }; void getStruct(struct point); struct point getStruct2(void); void output(struct point); int main(int argc, const char * argv[]) { /* - 結構和函數 - 結構作為函數參數: int numberOfDays(struct date d); 整個結構可以作為參數的值傳入函數 這時候是在函數內新建一個結構變量,並復制調用者的結構的值 也可以返回一個結構 這與數組是不一樣的 輸入結構: 沒有直接的方式可以一次scanf一個結構(就像%d這種) 寫一個函數來讀入結構 -> 但是讀入的結構如何送回來呢? 記住C在函數調用時是傳值的 在函數中的p與main中的y是不同的 在函數讀入了p的數值之後,沒有任何東西回到main,所以y還是{0, 0} 解決方案: 之前的方案,把一個結構傳入了函數,然後在函數中操作,但是沒有返回回去 問題在於傳入函數的是外面那個結構的克隆體,而不是指針 傳入結構和傳入數組是不同的 在這個輸入函數中,完全可以創建一個臨時的結構變量,然後把這個結構返回給調用者 結構指針作為參數: 如果一個大的結構傳到函數裡,通常更有效的是傳遞一個指針而不是拷貝整個結構 指向結構的指針: struct date { int month; int day; int year; } myday; //聲明一個date結構和結構變量myday struct date *p = &myday; (*p).month = 12; //點運算符 p->month = 12; //用->運算符表示指針所指的結構變量中的成員 結構指針參數: struct point* getStruct2(struct point *p) { scanf("%d", &(p->x)); scanf("%d", &(p->y)); return p; } void output(struct point p) { printf("%d, %d", p.x, p.y); } void print(const struct point *p) { printf("%d, %d", p->x, p->y); } void main() { struct point y = {0, 0}; getStruct2(&y); output(y); output(*getStruct2(&y)); printf(getStruct2(&y)); getStruct(&y)->x = 0; *getStruct(&y) = (struct point){1, 2}; } */ struct point y = {0, 0}; getStruct(y); output(y); //0, 0 傳的是結構變量y的"值",而不是指針,所以在getStruct內即使成員變量被賦值,不會影響y y = getStruct2(); //兩個結構變量可以賦值 output(y); //4, 5 return 0; } void getStruct(struct point p) { scanf("%d", &p.x); //2 scanf("%d", &p.y); //3 printf("%d, %d\n", p.x, p.y); //2, 3 } struct point getStruct2(void) { struct point p; //本地變量 scanf("%d", &p.x); //4 scanf("%d", &p.y); //5 printf("%d, %d\n", p.x, p.y); //4, 5 return p; } void output(struct point p) { printf("%d, %d\n", p.x, p.y); //0, 0 }
// main.c // Created by weichen on 15/7/5. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> struct time { int hour; int minutes; int seconds; }; struct time timeUpdate(struct time now); int main(int argc, const char * argv[]) { /* - 結構中的結構 - 結構數組 struct date dates[100]; // 聲明一個結構變量為數組 struct date dates[] = { // 初始化數組,每一個成員是struct {4,5,2005}, {2,4,2005} }; 結構中的結構 struct dateAndTime { struct date sdate; struct time stime; }; 嵌套的結構 struct point { int x; int y; }; struct rectangle { struct point pt1; struct point pt2; }; 如果有變量: struct rectangle r; 就可以有: r.pt1.x 、r.pt1.y, r.pt2.x 和 r.pt2.y 如果有變量定義: struct rectangle r.*rp; rp = &r; 那麼下面的四種形式是等價的: r.pt1.x #正常形式 rp->pt1.x #指針訪問結構變量的成員 (r.pt1).x #加括號形式,不影響 (rp->pt1).x #加括號形式,不影響 但是沒有rp->pt1->x(因為pt1不是指針),示意圖: |--------------| | |-----| | r . |pt1 . |x | | | |-----| | +-> | |y | | | | |-----| | | |pt2 . x | | | y | | |--------------| | | |--------------| rp | 指針 | |--------------| 結構中的結構的數組: struct point { int x; int y; }; struct rectangle { struct point p1; struct point p2; } void printRect(struct rectangle r) { printf("<%d, %d> to <%d, %d>\n", r.p1.x, r.p1.y, r.p2.x, r.p2.y); } int main(int argc, char const *argv[]) { int i; struct rectangle rects[] = { //2rectangles, 1,2是rects[0]的pt1的x和y,3,4是rects[0]的pt2的x和y {{1,2},{3,4}}, {{5,6},{7,8}} }; for (i=0; i<2; i++) { printRect(rects[i]); } } */ struct time testTimes[] = { {11,59,59}, {12,0,0}, {1,29,59}, {23,59,59}, {19,12,27} }; int i; for (i=0; i<5; i++) { printf("Time is %.2i:%.2i:%.2i\n", testTimes[i].hour, testTimes[i].minutes, testTimes[i].seconds); testTimes[i] = timeUpdate(testTimes[i]); printf("one second later is %.2i:%.2i:%.2i\n", testTimes[i].hour, testTimes[i].minutes, testTimes[i].seconds); } // 結構成員變量的sizeof即為類型的大小,結構變量的sizeof為成員變量的sizeof之和 // 結構內成員之間連續,相鄰成員的地址差不等於對應成員的sizeof struct time ab = {1, 5, 7}; printf("%ld, %ld, %ld, %ld\n", sizeof(ab), sizeof(ab.hour), sizeof(ab.minutes), sizeof(ab.seconds)); //12,4,4,4 printf("%p, %p, %p, %p, %ld\n", &ab, &(ab.hour), &(ab.minutes), &(ab.seconds), (&(ab.minutes) - &(ab.hour))); //0x7fff5fbff798, 0x7fff5fbff798, 0x7fff5fbff79c, 0x7fff5fbff7a0, 1 return 0; } struct time timeUpdate(struct time now) { ++now.seconds; if (now.seconds == 60) { now.seconds = 0; ++now.minutes; if (now.minutes == 60) { now.minutes = 0; ++now.hour; if (now.hour == 24) { now.hour = 0; } } } return now; }
結構和數組的聯系和區別
原本結構和數組沒什麼聯系。FORTRAN就出現了數組的概念,結構是在Algol中出現的,C++開始結構成為定義新的數據類型的主要方式。結構在編程語言中的地位是為了讓用戶可以定義集成在一起的一些量,給這個整體一個名字;而數組是為了表達能表達一連串相同類型的數據的。現在,如果離開C語言,站在更高的高度,我們如何看到結構和數組?
類型定義
// main.c // Created by weichen on 15/7/6. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> int main(int argc, const char * argv[]) { /* - 自定義數據類型(typedef) - C語言提供了一個叫做typedef的功能來聲明一個已有的數據類型的新名字,如: typedef int Length; // Length成為int類型的別名, 等價於int類型 typedef *char[10] Strings; // Strings是10個字符串的數組的類型,10個字符指針的數組 typedef struct node { int data; struct node *next; } aNode; 或 typedef struct node aNode; // 這樣用aNode就可以代替struct node 這樣,Length這個名字就可以代替int出現在變量定義和參數聲明的地方了: Length a,b,len; Length numbers[10]; Typedef 聲明新的類型的名字 新的名字是某種類型的別名 改善了程序的可讀性 typedef long int64_t; // 重載已有的類型名字,新名字的含義更清晰,具有可移植性 typedef struct ADate { // 在typedef和最後單詞中間的所有東西是它原來的類型 int month; int day; int year; } Date; // 簡化了復雜的名字 int64_t i = 1000000000; Date d = {9, 1, 2005}; // 把一個struct命名為Date (struct名字我們不關心,因為有更好的方式來表達它了 - Date) typedef struct { int month; int day; int year; } Date */ typedef struct { int month; int day; int year; } Date; Date a = {1,2,3}; printf("%ld,%ld,%ld", a.month, a.day, a.year); //1,2,3 return 0; }
// main.c // Created by weichen on 15/7/6. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> typedef union { int i; char ch[sizeof(int)]; } CHI; int main(int argc, const char * argv[]) { /* - 聯合 - 和struct非常相似 union AnElt { int i; char c; } elt1, elt2; // 成員是一個int i 還是一個char c, sizeof(union ...) = sizeof(每個成員)的最大值 elt1.i = 4; elt2.c = 'a'; elt2.i = 0xDEADBEEF; 和struct不一樣的是: 存儲 所有的成員共享一個空間 同一時間只有一個成員是有效的 union的大小是其最大的成員 初始化 對第一個成員做初始化 可以得到整數/float/double內部的各個字節 */ CHI chi; int i; chi.i = 1234; for (i=0; i<sizeof(int); i++) { printf("%02hhX", chi.ch[i]); //D2040000 } printf("\n"); return 0; }
Link:http://www.cnblogs.com/farwish/p/4604233.html
@黑眼詩人 <www.farwish.com>