// 引入頭文件。裏面包含了重要的 printf。編程
#include <stdio.h>數組
// 入口函數。函數
// 參數一指輸入的參數個數,參數二保存了全部參數。學習
// 返回值爲 int 類型,通常 0 表明成功,負數表明失敗。編碼
int main(int argc,char* argv[]){spa
printf("Hello World!\n");操作系統
return 0; // 表明執行成功。debug
}指針
————————調試
經過指令的編譯與執行:
MAC 下的編譯使用 clang,Linux 下的編譯使用 gcc。
gcc/clang -g -o Hello xxx.c
● -g 是 debug 模式,帶有調試信息的。
● -o 指明輸出文件的名字
● xxx.c 源代碼
在 MAC 或 Linux 下使用 ./Hello 來執行
集成環境的運行,後臺其實也是這個步驟。
short(短整型)、int(整型)、long(長整型)
float(單精度浮點型,通常狀況使用 float。)、double(雙精度浮點型,精度高,適用於科學計算等。)
char(字符)、char*(字符串)
void(對類型不關心時)
+、-、*、/、%
int main(int argc,char* argv[]) { int a = 10; float b = 12.5; // 打印結果;a+b=22.500000 (float 類型) printf("a+b=%f\n",a+b); // 打印結果;... , a*b=125.000000 (float 類型) printf("a+b=%f\n,a*b=%f\n",a+b,a*b); char c = 'a'; // 打印結果;c=f(c 爲字符 a,c 加數字能夠變爲另外一個字符,c+1=b,c+2=c,...) printf("c=%c\n",c+5); // 打印結果;c=102(f 的實際編碼的值就是 102) printf("c=%d\n",c+5); int d = 10; int e = d % 6; // 取餘 int f = d / 6; // 取商 // 打印結果;e=4,f=1 printf("e=%d\n,f=%d\n",e,f); return 0; // 表明執行成功。 }
● int a = 0; // 變量,能夠再賦值。能夠不賦值初始值。
變量在計算機中的物理意義,就是一個寄存器。寄存器是臨時存儲數據的,它的速度很是快。從內存中取一塊數據時,首先存儲到寄存器,當改變這個值時,刷新的是寄存器,可擦除。這樣能夠加快程序的執行速度。
● const int len = 265; // 常量,不可改變。須要賦值初始值。
在編譯程序時,程序中設定了一段靜態緩衝區,靜態緩衝區是受保護的,經過正常途徑是不可修改的。但若是知道內存的具體物理地址,也是能夠改變的。
數組是有序的元素序列(C 語言的數組存放的是同一種類型的元素,索引從 0 開始),C 語言中定義數組須要告訴編譯器數組的長度。C 語言中數組的定義; char c[2], int arr[10]
int main(int argc,char* argv[]) { // int arr[10]; // arr[0] = 1; // arr[1] = 2; // printf("%d,%d\n",arr[0],arr[1]); int arr[10] = {1,2,3,}; // 打印結果;1,2,3,0(默認狀況下,不賦值的狀況下,數組會初始化爲 0。) printf("%d,%d,%d,%d\n",arr[0],arr[1],arr[2],arr[3]); float f[2] = {1,2}; // 打印結果;1.000000,2.000000 printf("%f,%f\n",f[0],f[1]); return 0; }
// 它是沒有保護的概念的(如 private 等) struct st { int a; // 成員 a int b; // 成員 b };
// 結構體能夠理解爲它是一個類 struct st{ int a; float f; }; int main(int argc,char* argv[]){ struct st ss; ss.a = 12; ss.f = 10.2; // 打印結果;struct:12, 10.200000 printf("struct:%d, %f\n",ss.a,ss.f); return 0; // 表明執行成功。 }
枚舉能夠認爲它是一個有限制的整型。通常狀況下的使用,是在有必定數值範圍的,好比某個屬性的取值只能爲 一、二、3。
enum em { red_color = 0, // 值爲 0,若是值爲 1 green_color, // 值爲 1,則值爲 2 black_color // 值爲 2,則值爲 3 };
enum em { red_color = 5, green_color, black_color = 10, yellow_color }; int main(int argc,char* argv[]){ enum em ee; ee = green_color; // 打印結果;enum:6 printf("enum:%d\n",ee); ee = yellow_color; // 打印結果;enum:11 printf("enum:%d\n",ee); return 0; // 表明執行成功。 }
指針就是存放內存地址的變量。地址空間內的存的值,在 C 語言中,它除了能夠存放普通的數值,還能夠存放另外一個內存的地址,這個值就是指針,經過這個值就能夠訪問到其它地址,而後就能夠取出這個地址所存放的數據。因此,這個值能夠有多重含義,具體跟業務邏輯相關。
一、指針的做用:
● 提高執行效率。
通常狀況下,將字符串傳入函數中,函數對字符串進行操做時,它是一個拷貝的過程,函數將字符串拷貝到本身的函數空間存放起來。屢次的拷貝會對整個 CPU 形成巨大的浪費。而指針,只須要向函數傳遞這個字符串所在的地址,函數經過指針訪問字符串。
● 更強的控制力。
由於它具備訪問地址的能力。像計算機的硬件實際到操做系統層都會有一個對應的映射地址,經過這個地址,C 語言就能訪問到硬件設備,並進行控制。C 語言是更底層的語言,它能夠訪問設備。
二、指針的操做:
● 對指針自己的操做。
實際就是對地址的操做。好比,當獲取某個空間的指針後,能夠對這個指針進行加減乘除的操做,對其加一,就指向了下一個空間。
● 對所指向的內容操做。
指針指向某一個內存地址時,能夠獲取其內容,能夠對這個內容進行加減乘除的操做。
三、指針的定義與使用:
● type* var:type 指類型,好比 int、void 等。
而 * 表明這個變量是一個指針,能夠靠近類型 type 寫,表示這種類型的指針,關注指針是什麼類型的,也能夠靠近變量 var 寫,表示這個變量是一個指針,而對類型不關注。這兩種寫法對編譯器是沒有區別的,但在編寫代碼時,最好統一風格。
● *var:表示獲取指針所指向的內容
四、堆內存的分配與釋放:
● 分配內存:void* mem = malloc(size);
● 釋放內存:free(mem);
#include <stdio.h> #include <stdlib.h> // malloc() 須要的頭文件 int main(int argc,char* argv[]){ // malloc() 通常返回的是 void* 類型。 // malloc() 在 <stdlib.h> 頭文件中。 char* p = (char*)malloc(10); // 分配十個字符的空間 *p = 'a'; // 第一個字符的位置 *(p+1) = 'b'; // 第二個字符的位置 // 將內存分配的地址告訴 printf, // printf 將 p 地址所指向的空間的內容以字符串的形式打印出來。 printf("%s\n",p); // 打印結果;ab // 將 p 所指向的空間釋放掉 // 系統管理層將內存又還給了堆空間 free(p); *p = 'd'; // 即便把空間釋放掉,但由於仍然掌握此空間的位置,知道 p 的指向。 // 因此即便被釋放掉了,仍是能夠對其操做。 printf("%s\n",p); // 打印結果;db // 因此爲了避免讓再訪問這個地址,要將其指向 NULL,設置爲無效地址。 p = NULL; // *p = 'e'; // crash return 0; }
● 棧空間:棧的機制,後進先出。最大的特色是,在 C 語言中寫的函數,在函數內所分配的全部變量都是在棧空間分配的,當從函數退出時,從棧空間分配的資源會被自動釋放。
分配的資源是有限的,默認每一個函數棧空間的大小是 8兆。
● 堆空間:須要明確的使用 malloc() 函數來分配資源,使用完內存後,要經過 free() 函數將資源釋放回堆空間,這樣別人使用時還能從堆空間分配資源。
分配的資源幾乎能夠認爲是無限的,適合須要大空間的時候。
● 內存映射:像一些動態庫通常都是將它直接導入內存映射區,也是一段專門的空間。
好比將某個文件直接映射到內存中,文件的內容與內存造成映射關係,當改變內存中的值時,會直接在系統內部自動更新到文件中。
● Linux 內存地址的劃分:4G 32 位系統
0 ~ 0x08048000:這段是受保護空間,咱們的進程是不能訪問的。
code:存放的是進程所要執行的代碼段。
堆空間的增加是從下向上,棧空間是從上向下,每次分配空間是向下走的。堆空間與棧空間這樣的劃分是爲了減小衝突。
共享庫,或者叫內存映射區,當想經過內存改變文件時,就能夠將文件映射到 mmap 這段空間中。
● 內存泄漏:
▷ 不斷的向系統申請內存。
▷ 申請的內存不用,也不釋放。
● 野指針:佔用別人的內存稱爲野指針。
比較運算:
>、<、>=、<=、==、!=
if/else 語句:
if( a> b){ ... }else{ ... }
for 語句:
for(int i =0; i<100; i++){ ... }
while 語句:
#include <stdio.h>
#include <unistd.h> // usleep() 須要的頭文件
int main(int argc,char* argv[]){
while (1) { // 死循環
printf("while...\n"); // 一秒鐘打印一次
usleep(1000000); // 微秒
}
return 0;
}
C 語言中的命名通常以 Linux 的風格,單詞與單詞用下劃線鏈接,單詞通常都是縮寫。
// void 返回類型
// func 函數名稱
// int a 形參
void func(int a){
... // 函數不能太大,通常不超過 50 行。
}
● 函數指針:指向函數的指針變量。經過 C 語言的函數指針能夠實現 C++ 中的多態,就是定義的函數指針既能夠指向 a 函數,也能夠指向 b 函數,對外層來講,只須要調用這個函數指針就能夠了。(多態就是指一個函數能夠有不一樣的含義)
● 函數指針的格式:返回值類型 (*指針變量名) ([形參列表]);
————————
int func(int x); // 聲明一個函數 int (*f)(int x); // 聲明一個函數指針。返回類型和形參必須與指定的函數一致。 f = func; // 將 func 函數的首地址賦值給指針 f。而後調用 f 便可。 ———————— #include <stdio.h> int func(int a){ printf("a=%d\n",a); return 0; } int func1(int b){ printf("b=%d\n",b+5); return 0; } int main(int argc,char* argv[]){ int (*f)(int); // 在 C++ 中這就是多態。 // 對上層來說,調用的都是 f 這個函數指針,但在底層返回的是不一樣的結果。 f=func; f(2); f=func1; f(3); // 打印結果;a=2 b=8 return 0; }
● 文件類型:FILE* file; (FILE* 在 Linux 下叫指針,在 Windows 下叫句柄。)
● 打開文件:FILE* fopen(path,mode);
● 關閉文件:fclose(FILE*);
#include <stdio.h> void createfile(char* filename){ // open/create file FILE* file = fopen(filename,"w"); if (!file) { printf("Failed to create file (%s)\n",filename); return; } // 向建立好的文件內寫入內容。 // 參數一指寫入的字符串,參數二指字符串中的每一項多大,參數三指一共有幾項,參數四指寫到哪一個文件 size_t len = fwrite("aaaaa", 1, 5, file); if (len !=5) { // size_t 使用的打印爲 %zu。 printf("Failed to write file,(%zu)",len); fclose(file); return; } printf("Successed to write file\n"); fclose(file); printf("Successed to create file\n"); } void read_data(char* filename){ FILE* file = fopen(filename,"r"); if (!file) { printf("Failed to create file (%s)\n",filename); return; } // 定義爲 1k 大小,並初始化爲 0。 char buffer[1024] = {0,}; // 參數:讀出的數據存放位置,長度,讀多少,從哪讀。 size_t len = fread(buffer, 1, 10, file); if (len <= 0) { printf("Failed to read file!\n"); fclose(file); return; } printf("read_data:%s\n",buffer); fclose(file); return; } int main(int argc,char* argv[]){ // create file // createfile("/Users/jianghouren/Downloads/1.txt"); // read file read_data("/Users/jianghouren/Downloads/1.txt"); return 0; }
最後,無論你是轉行也好,初學也罷,進階也可,若是你想學編程~
【值得關注】個人 C/C++編程學習交流俱樂部!【點擊進入】
問題答疑,學習交流,技術探討,還有超多編程資源大全,零基礎的視頻也超棒~