【C語言核心基礎】基本運算、變量、數組、指針、函數、結構體...

C 語言基礎

// 引入頭文件。裏面包含了重要的 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 來執行

集成環境的運行,後臺其實也是這個步驟。

 

1、經常使用基本類型

    short(短整型)、int(整型)、long(長整型)

    float(單精度浮點型,通常狀況使用 float。)、double(雙精度浮點型,精度高,適用於科學計算等。)

    char(字符)、char*(字符串)

    void(對類型不關心時)

 

2、基本運算

+、-、*、/、%

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;  // 表明執行成功。

}

 

3、變量與常量

    ● int a = 0; // 變量,能夠再賦值。能夠不賦值初始值。

變量在計算機中的物理意義,就是一個寄存器。寄存器是臨時存儲數據的,它的速度很是快。從內存中取一塊數據時,首先存儲到寄存器,當改變這個值時,刷新的是寄存器,可擦除。這樣能夠加快程序的執行速度。

    ● const int len = 265; // 常量,不可改變。須要賦值初始值。

在編譯程序時,程序中設定了一段靜態緩衝區,靜態緩衝區是受保護的,經過正常途徑是不可修改的。但若是知道內存的具體物理地址,也是能夠改變的。

 

4、數組

數組是有序的元素序列(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;

}

 

5、結構體

// 它是沒有保護的概念的(如 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;  // 表明執行成功。

}

 

6、枚舉類型

枚舉能夠認爲它是一個有限制的整型。通常狀況下的使用,是在有必定數值範圍的,好比某個屬性的取值只能爲 一、二、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;  // 表明執行成功。

}

 

7、指針

指針就是存放內存地址的變量。地址空間內的存的值,在 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;

}

 

8、常見的內存空間

● 棧空間:棧的機制,後進先出。最大的特色是,在 C 語言中寫的函數,在函數內所分配的全部變量都是在棧空間分配的,當從函數退出時,從棧空間分配的資源會被自動釋放。

分配的資源是有限的,默認每一個函數棧空間的大小是 8兆。

● 堆空間:須要明確的使用 malloc() 函數來分配資源,使用完內存後,要經過 free() 函數將資源釋放回堆空間,這樣別人使用時還能從堆空間分配資源。

分配的資源幾乎能夠認爲是無限的,適合須要大空間的時候。

● 內存映射:像一些動態庫通常都是將它直接導入內存映射區,也是一段專門的空間。

好比將某個文件直接映射到內存中,文件的內容與內存造成映射關係,當改變內存中的值時,會直接在系統內部自動更新到文件中。

● Linux 內存地址的劃分:4G 32 位系統


 

0 ~ 0x08048000:這段是受保護空間,咱們的進程是不能訪問的。

code:存放的是進程所要執行的代碼段。

堆空間的增加是從下向上,棧空間是從上向下,每次分配空間是向下走的。堆空間與棧空間這樣的劃分是爲了減小衝突。

共享庫,或者叫內存映射區,當想經過內存改變文件時,就能夠將文件映射到 mmap 這段空間中。

● 內存泄漏:

    ▷ 不斷的向系統申請內存。

    ▷ 申請的內存不用,也不釋放。

● 野指針:佔用別人的內存稱爲野指針。

 

9、條件判斷與循環

比較運算:

>、<、>=、<=、==、!=

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;

}

 

10、函數

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;

}

 

11、文件操做

    ● 文件類型: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++編程學習交流俱樂部!【點擊進入】

問題答疑,學習交流,技術探討,還有超多編程資源大全,零基礎的視頻也超棒~

相關文章
相關標籤/搜索