首頁 > 軟體

C語言學習基礎知識分享

2023-01-24 14:01:15

寫在前面

我們正式開始接觸到C語言,這是我在學習過C語言後重新寫的部落格,我把之前的稍微優化了一下,希望能用更加樸素的語言和大家分享,我希望給大家帶來一個可以看的懂,理論和實踐並行的內容.當然裡面也會存在一些錯誤和不恰當的地方,還請諸位指正.

為何學習C語言

我想從兩個方面和大家分析學習C語言的必要性和好處.

語言層面

我們先來下一個結論 C生萬物,程式設計之本, 很多人學習計算機都是從C語言開始的,它是長遠IT職業發展的首選,C語言是母體語言,是人機互動接近底層的橋樑 ,學會 C語言,相當於掌握技術核心 . IT行業,一般每10年就有一次變革,40年間,在 TIOBE 排行榜中,C/C++位置長期霸佔前三名,沒有絲毫撼動,可謂經典永不過時!

個人層面

在當今社會,技術不斷的發展和更新,語言更是層出不窮的出現,C++、Java、、python、go.語言實在是太多了,那麼我們為何還要學一門很老的語言,我們學習最新的語言不是可以更好的適應當前技術的迭代嗎?

每個人都有每個人的理解,首先我來說一下自己的觀點.和大多數人一樣,我接觸的第一門語言就是C語言,那時的我感覺內容多,而且還很難理解,尤其是後面的指標一直在困擾著我,但是當我在後面逐漸學習的其他語言後,C語言的很多理念出現在其中,尤其是一脈相承的C++.C語言的學習可以大大提高我們學習其他語言的能力.

初識C語言

我想分為兩個部落格的內容和大家整體的過一下C語言的基本知識,這樣我們看別人的程式碼可以看的懂.我認為大家對他有一個認識是非常重要的,這樣即使我們深度不夠,也有往下探究的慾望.

什麼是語言

在現實生活中我們可以很容易的知道人與人交流是通過語言來進行交流的, 人和人可以用漢語,英語,俄語...進行交流,那麼人和計算機呢?或者說計算機和計算機是通過什麼語言交流的?這就是計算機語言. C語言是常見的一種計算機語言,每一個語言都有自己的優點,也有自己的缺點,C語言同樣如此,相比較於其他的語言,C語言更加適合底層開發, 注意C語言是適合底層開發,不意味著只能幹,我們也可以使用C語言做上層的業務.

標準

什麼事物要想發展要好,必須要有標準.那麼什麼是標準,在早期我們是通過二進位制程式設計的,,很多人要查手冊,這裡很難,所以那個時候一般研究這些的都是都是科學家.此時有很多科學家覺得我們使用二進位制是在是太麻煩了,受不了了,我們給二進位制序列起一個名字,例如張三和身份正好對應,我們把這些名字稱之為助記符,後面又發展成組合語言,B語言,C語言和後面的很多語言.

C語言很優秀,很多廠商會對C語言進行客製化,自己增加自己的語法,這個時候就出現了差異,這就是雜亂尺寸生,此時又權威的一些人提出了國際標準,也就是K&R標準,這就是標準.後來標準進行迭代,逐漸的迭代出其他的版本,例如流行的C89標準,和後面的C90,C99.主流標準是C89和C90,C99之後都比較少一些,我們主要看C89的知識點.

helloword

我們來認識第一個程式碼,這是我們幾乎每一個程式設計師都寫過的程式碼.

#include <stdio.h>
int main()
{
  printf("hello,worldn");
  return 0;
}

main

如果你已經嘗試了上面的程式碼,覺得既新奇又飽含疑惑,那麼下面我們先來簡單的揭開它的面紗.注意,我們找個部落格的目的是可以簡單的上手C語言,會用就可以了,至於它的原理隨著我們學習的深入,我們都會逐漸明白的,所以說不要著急.

<font color = red>我們規定main函數是程式的入口</font>,注意,這裡標準直接這樣規定的,也就是說我們啟動一個程式時,編譯器會自動的找到main函數,然後從上往下的開始執行裡面的程式碼.

我們這裡需要看一下main函數的大體框架,後面我們要嚴格按照這個格式來寫,至於為什麼這裡都等到函數那裡去談.

int main()
{
    // 程式碼
    return 0;
}

在一些比較老的程式碼規範裡面,還存在下面的寫法,這裡我們強烈不推薦.,他們實在是太老了,而且看著還很彆扭.

void main()
{

}

printf

我們從main入口進入了,現在我們開始在想,我們程式的目的是往螢幕上列印Hello World,所以我們呼叫了一個函數,函數相關的細節我們會單獨分享.這個時候我告訴你在標準庫裡面有一個printf函數可以幫助我們完成這個功能,我們要用這個函數,這裡需要引一個標頭檔案stdio.h,我們通過下面的做法來達到這個目的.

#include <stdio.h>

到這裡解決我們大部分疑惑,也可以簡單的上手寫一些程式碼了.

#include <stdio.h>
int main()
{
  printf("我是C語言的初學者");
  return 0;
}

資料型別

我們都知道,我們可以從不同的角度來描述一個物體,假如說這有一個箱子,我們可以這樣描述.

這裡你會發現有不同的資料型別,存在整數和小數,甚至名字是一串字元.我們計算機要模擬世界,那麼肯定要提供這些型別,C語言就給我們內建了很多的資料型別,我們先來見識一下.

資料型別

說明

大小

char

字元型別

1 位元組

short

短整型

2 位元組

int

整型

4 位元組

long

長整型

4 位元組

long long

更長的整形

8 位元組

float

單精度浮點數

4 位元組

double

雙精度浮點數

8 位元組

回答一下下面的問題:

為什麼要定義這麼多型別?

我們的應用場景是非常複雜的,不同應用場景要求不同大小的空間,比如說,一個人的年齡、身高等變數可以定義成short型,定義成 int型就浪費了空間。

這些型別的大小是什麼意思?

根據不同的型別在記憶體中開闢不同大小的一塊空間,每個型別開闢的空間是固定的,至於如何計算,這個我們下面談

byte & bit

在回答不同型別佔據的空間前我們先來看一下計算機裡面的一些單位.這裡我們用一個宿舍樓來進行舉例子.在一所高校中,我們把一棟宿舍樓分成很多個小宿舍,每一個小宿舍都有固定的床位.計算機同樣如此,在計算機中,一塊很大的記憶體,我們把他分成很多個小空間,這個空間名字叫做位元組(byte),這裡我們首先要強調的是位元組是記憶體的基本單位.和每個小宿舍有這個固定床位一樣,每一個位元組又會被分為八個區域,這個區域叫做位元位(bit),也就是一位元組等於八個位元位.

sizeof

上面回答了記憶體的基本單位,這裡就理解不同的資料型別佔據若干的位元組是什麼意思了.這個時候我們又在想,我們是不是可以驗證一下,你在這裡一直給我灌輸理論,總是感覺有點不踏實.這裡我們就要請出sizeof這個關鍵字.我們先來解釋一下什麼是關鍵字.

我這裡直接說我的理解,所謂的關鍵字是C語言官方給我們提供的,這些關鍵字有著不同的功能,比如說上面的int,我們可以很清楚的知道int代表的是一個整型.sizeof也是一個關鍵字,它的作用是計算佔據記憶體空間的大小,單位就是位元組.後面我們會遇到很多關鍵字,我們用一個談一個.現在開始驗證一下這些型別的大小,你會發現printf又出現了新的用法,這個後面會談到,先暫時這樣用著.

#include <stdio.h>
int main()
{
  printf("char       %dn", sizeof(char));
  printf("short      %dn", sizeof(short));
  printf("int        %dn", sizeof(int));
  printf("long int   %dn", sizeof(long int));
  printf("long long  %dn", sizeof(long long));
  printf("float      %dn", sizeof(float));
  printf("double     %dn", sizeof(double));
  system("pause");
  return 0;
}

常數

生活中的有些值是不變的(比如:圓周率,性別(?),身份證號碼,血型等等),有些值是可變的(比如:年齡,體重,薪資)。 在C語言中,我們會學習到變數,常數,作用域,生命週期......等概念,我們不由得發出疑問,什麼是變數,為什麼要有變數?這些都是我們需要處理得疑惑.我先談談常數,後面再說說變數。所謂的常數就是不可再次修改的資料.它有下面的幾種分類.

數值常數 1,2,3...字串常數 "abcd","defcbg"

這裡面我重點談談字串常數,在C語言中,存在一個字串常數池,這個我們等到作業系統再談,像"abcd"就是其中的一部分,要是我們想要修改"abcd"變為"bbcd",這是做不到的,有的人可能會感到疑惑,這不是很簡單嗎,我們只需要把a修改成b不就完成了嗎?但是這只是象,"bbcd"也是字串常數池的一部分,我們所謂的修改,就是更改指標所指向的地址(指標後面談).

#include <stdio.h>

int main()
{
  char* pa = "abcd";
  printf("%pn", pa);

  pa = "bbcd";
  printf("%pn", pa);
  return 0;
}

常數分類

上面的太籠統 這類簡單的說一下,在C語言中我們將學習不同的常數.

字面常數 就是字元const 修飾的常變數列舉 後面談#define 定義得的識別符號常數

注意:const是一個關鍵字,這個關鍵字作用是很大的,我們後面會重點分析.

變數

簡單得來說,變數就是可以修改得量.變數不同於常數,它可以被修改的.例如int x = 10,x可以修改為20,但是我們不能把常數1修改成常數2.這就是變數定義.<font color = red>在計算機中,變數是一個在記憶體中開闢特定大小的空間,用來儲存資料. </font>

定義變數

這倒是很簡單,就是<font color = blue>型別 變數名 = 初始化的值</font>.這裡我們需要談一下什麼是變數名,前面我們描述箱子的時候,談到了長度,我們用L表示,此時這裡就可以認為L就是一個變數.

int a = 10;          // 定義一個整型變數a  並初始化為 10
double b = 10.2;     // 定義一個雙精度浮點數變數b  並初始化為 10

變數的分類

變數的分類主要分為兩大類,我們儘量不要使用全域性變數.

  • 全域性變數
  • 區域性變數

區域性變數

區域性變數:包含在程式碼塊中的變數叫做區域性變數。區域性變數具有臨時性。進入程式碼塊,自動形成區域性變數,退出程式碼塊自動釋放.(網上很多說函數中的變數是區域性變數,不能說錯,但說法是不準確的),下面的a和d都是區域性變數.

int main()
{
  int a = 10;
  double d = 11.01;
  return 0;
}

這裡來個複雜的,這裡就可以驗證一下區域性變數具有臨時性,這裡的臨時性可以認為對標下面的作用域和生命週期.

#include <stdio.h>

int main()
{
  int a = 10;
  {
    int x = 20;
    printf("x = %dn", x);
  } return 0;
}

這裡的臨時性就可以通過下面的程式碼驗證出來

#include <stdio.h>

int main()
{
  int a = 10;
  {
    int x = 20;
    printf("x = %dn", x);
  }
  printf("x = %dn", x);

  return 0;
}

區域性變數如果不進行初始化,那麼根據編譯器的不同,我們拿到的是隨機值,甚至嚴格的編譯器都不會讓我們使用.

我們在測試一下gcc編譯器,這裡看看有什麼不同.看來gcc是沒有VS嚴格的,但是我們要按照最標準的來,嚴格遵守變數被定義一定要初始化.

全域性變數

這裡我想和大家談談全域性變數,這個有一點重要.所謂的全域性變數,全域性變數具有全域性性 , 我們可以認為是在main函數外邊所定義的變數,一般按照<font color = bluee>g_變數名</font>的格式來走,當然,也可以不按.

#include <stdio.h>

int g_key = 20;        //全域性變數
double g_val = 10.00;

int main()
{

  printf("%dn", g_key);
  printf("%dn", g_val);
  return 0;
}

上面我們談到了區域性變數不進行初識化是隨機值,那麼全域性變數呢?這是很簡單的,我們直接給一個結論,全域性變數定義起來即使我們不初始化,他也是固定值,是0.這裡只驗證VS.

int a;
int main()
{
  printf("%dn", a);
  return 0;
}

注意,如果你堅持看我後面寫的部落格,就會發現我們很少使用全域性變數,它是有一定的缺陷的,等到後面我們會專門談的.

區域性優先

大家看一下下面的程式碼.<font color = red>如果全域性變數和區域性變數同名,編譯器優先使用區域性變數,這就是區域性優先原則.</font>

#include <stdio.h>
int a = 10;
int main()
{
  int a = 0;
  printf("a = %dn", a);
  return 0;
}

變數的使用

我們先來簡單色的通過格式化輸入輸出來分析一下變數是如何被我門使用的,這些都是很簡單的.

printf

這裡我們需要再次談一下printf函數,上面我們已經使用過它的用法了,可能大家會有一些疑惑,這裡需要具體的分析一下這個函數.

printf()函數是我們經常使用的的函數之一,他的作用就是將我們想要的資料輸出到指定位置,這裡的指定位置包含螢幕,我們先使用一下

#include <stdio.h>

int main()
{
  int a = 10;
  printf("%dn", a);
  return 0;
}

這裡我們可以看到,我們使用了printf()函數

printf("%dn",a);

這裡有幾點要說一下

% 被稱為 "轉換說明",所謂的轉換說明就是將資料按指定的格式顯式出來%d是指將a的值以十進位制的形式列印來,例如 %o :列印八進位制、%x 列印十六進位制.....

資料輸出的格式與很多,下面我列出一張表

X

例子

說明

d

%d

列印int型,預設1

f

%f

列印float型,小數點後預設6位

e

%e

以科學計數法的形式列印,小數點後預設6位

g

%g

以科學計數法或者float型列印,方式看g的大小選擇

scanf

我們在想既然變數是可以變化的,我們總不能把先要的值全部列出來吧,我們如果手動輸入該如何做到呢?這裡給大家簡紹一個scanf函數.

和printf() 一樣,scanf()也是存在特定的格式讀入,這裡先給出個例子,我們一起來看看

#include <stdio.h>

int main()
{
  int a = 0;
  scanf("%d", &a);
  printf("%dn", a);
  return 0;
}

作用域&生命週期

這個一直是一個比較容易模糊的點,有很多人對他們的區別可能分不太清楚,一般我們能分辨清楚就可以了

作用域 變數可以被使用的地方,就是作用域生命週期 變數開始開闢空間 到 空間銷燬

這裡我先給出點結論,適合大部分情況.區域性變數的作用域和生命週期是在區域性變數所在的程式碼塊中,除了程式碼塊就不可以了.全域性變數的作用域和生命週期是整個程式.

到此這篇關於C語言學習基礎知識分享的文章就介紹到這了,更多相關C語言基礎內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com