C 語言是一種通用的高級語言,最初是由丹尼斯·裏奇在貝爾實驗室爲開發 UNIX 操做系統而設計的。C 語言最開始是於 1972 年在 DEC PDP-11 計算機上被首次實現。編程
在 1978 年,布萊恩·柯林漢(Brian Kernighan)和丹尼斯·裏奇(Dennis Ritchie)製做了 C 的第一個公開可用的描述,如今被稱爲 K&R 標準。微信
UNIX 操做系統,C編譯器,和幾乎全部的 UNIX 應用程序都是用 C 語言編寫的。因爲各類緣由,C 語言如今已經成爲一種普遍使用的專業語言。app
易於學習。ide
結構化語言。函數
它產生高效率的程序。工具
它能夠處理底層的活動。佈局
它能夠在多種計算機平臺上編譯。post
這是隻說明在 MAC 上怎麼使用 C 語言來進行開發,環境的話須要用到 GCC 進行編譯,你能夠下載並安裝 Xcode 工具,一旦安裝上 Xcode,您就能使用 GNU 編譯器。開發工具你可使用 Xcode 或者 CLion 均可以,看我的喜愛。我這裏用的是 CLion 工具,你能夠發現 CLion 頁面跟使用風格包括快捷鍵都跟 AndroidStudio 同樣。上手極其容易。學習
咱們先來看一下最簡單的一個 C 程序,先來打印一個 「HelloWorld」。代碼以下:開發工具
#include <stdio.h>
/**
* C 語言入口程序
* @return
*/
int main() {//主函數,程序從這裏開始執行
printf("C 語言入門第一行代碼 Hello World! \n");
return 0;
}
能夠看到 C 語言的入口函數跟 Java 的相似吧,都是以main來定義的入口,接下來咱們講解一下上面這段程序的意思:
(1)程序的第一行#include <stdio.h>是預處理器指令,告訴 C 編譯器在實際編譯以前要包含 stdio.h 文件。
(2)下一行 /.../ 將會被編譯器忽略,這裏放置程序的註釋內容。它們被稱爲程序的註釋。
(3)下一行int main()是主函數,程序從這裏開始執行。
(4)下一行printf(...)是 C 中另外一個可用的函數,會在屏幕上顯示消息 "C 語言入門第一行代碼 Hello World!"。
(5)下一行return 0;終止 main() 函數,並返回值 0。
固然你能夠經過命令來執行,以下所示:
1. 使用 gcc xxx.c
2. ./a.out
直接使用上面 2 個步驟就能夠進行執行 C 代碼了。
上一小節咱們知道了一個簡單的小應用由哪些部分組成,這將有助於咱們理解 C 語言的其它基本的構建塊。
c 程序由各類令牌組成,令牌能夠是關鍵字、標識符、常量、字串符值、或者是一個符號。
下面咱們來看一下 C 中的關鍵字,這些關鍵字不能做爲常量名,變量名或者其它標識符名稱(跟 Java 相似)。
在 C 語言中,數據類型指的是用於聲明不一樣類型的變量或函數的一個普遍的系統。變量的類型決定了變量存儲佔用的空間,以及如何解釋存儲的位模式。
C 中的類型可分爲如下幾種:
整數類型
下表列出了關於標準整數類型的存儲大小和值範圍的細節
注意: 各類類型的存儲大小與系統位數有關,但目前通用的以 64 爲系統爲主。
浮點類型
他們的字節,精度,取值範圍均可以經過代碼打印實現,以下:
void main() {
/**
* 整數類型
*/
printf("\n\n 整數類型 \n");
//char 1 字節
printf("char 存儲大小: %lu \n", sizeof(char));
printf("unsinged char 存儲大小: %lu \n", sizeof(unsigned char));
//short 2 字節
printf("short 存儲大小: %lu \n", sizeof(short));
printf("unsinged short 存儲大小: %lu \n", sizeof(unsigned short));
//int 4 字節
printf("int 存儲大小: %lu \n", sizeof(int));
printf("unsinged int 存儲大小: %lu \n", sizeof(unsigned int));
//long 4/8 字節
printf("long 存儲大小: %lu \n", sizeof(long));
printf("unsinged long 存儲大小: %lu \n", sizeof(unsigned long));
/**
* 浮點類型
*/
printf("\n\n 浮點類型 \n");
//float 4 字節 ,精度 6 位小數
printf("float 存儲最大字節數:%lu \n", sizeof(float));
printf("float 最小值:%e \n", FLT_MIN);
printf("float 最大值:%e \n", FLT_MAX);
printf("float 精度值:%d \n", FLT_DIG);
//double 8 字節
printf("double 存儲最大字節數:%d \n", sizeof(double));
printf("double 最小值:%e \n", DBL_MIN);
printf("double 最大值:%e \n", DBL_MAX);
printf("double 精度值:%d \n", DBL_DIG);
//long double 16 字節
printf("long double 存儲最大字節數:%lu byte \n", sizeof(long double));
printf("long double 最小值:%lg \n", LDBL_MIN);
printf("long double 最大值:%lg \n", LDBL_MAX);
printf("long double 精度值:%d \n", LDBL_DIG);
}
能夠經過 sizeof 關鍵字來獲取數據類型佔用內存的大小。上面代碼能夠看到了打印中出現了不少不識的 scanf() 格式控制符,我總結了一個表,能夠參考下;
變量其實只不過是程序可操做的存儲區的名稱。C 中每一個變量都有特定的類型,類型決定了變量存儲的大小和佈局,該範圍內的值均可以存儲在內存中,運算符可應用於變量上。
變量的名稱能夠由字母、數字和下劃線字符組成。它必須以字母或下劃線開頭。大寫字母和小寫字母是不一樣的,由於 C 對大小寫敏感的。
C 中的變量定義
變量定義就是告訴編譯器在何處建立變量的存儲,以及如何建立變量的存儲。變量定義指定一個數據類型,幷包含了該類型的一個或多個變量的列表,以下所示:
type list;
在這裏,type必須是一個有效的 C 數據類型,能夠是 char、w_char、int、float、double 或任何用戶自定義的對象,list能夠由一個或多個標識符名稱組成,多個標識符之間用逗號分隔。下面列出幾個有效的聲明:
int a,b,c;
char c1,c2,c3;
float f,f1,f2;
double d1,d2,d3;
這裏其實跟 Java 聲明變量差很少,就再也不單獨解釋了。
c 中變量聲明
變量聲明向編譯器保證變量以指定的類型和名稱存在,這樣編譯器在不須要知道變量完整細節的狀況下也能繼續進一步的編譯。變量聲明只在編譯時有它的意義,在程序鏈接時編譯器須要實際的變量聲明。
變量的聲明有兩種狀況:
一、一種是須要創建存儲空間的。例如:int a 在聲明的時候就已經創建了存儲空間。
二、另外一種是不須要創建存儲空間的,經過使用 extern 關鍵字聲明變量名而不定義它。 例如:extern int a 其中變量 a 能夠在別的文件中定義的。
三、除非有 extern 關鍵字,不然都是變量的定義。
extern int i;//聲明,不是定義
int a;//聲明,也是定義
例子
#include <stdio.h>
//函數外定義變量
//若是須要在一個源文件中引用另一個源文件中定義的變量,咱們只需在引用的文件中將變量加上 extern 關鍵字的聲明便可
int x;
int y;
int sum() {
//函數內聲明變量 X , Y 爲外部變量
x = 10;
y = 15;
return x + y;
}
//入口函數
void main() {
//打印變量相加
int result;
result = sum();
printf("x + y = %d",result);
}
輸出:x + y =25
常量是固定值,在程序執行期間不會改變。這些固定的值,又叫作字面量。
常量能夠是任何的基本數據類型,好比整數常量、浮點常量、字符常量,或字符串字面值,也有枚舉常量。
常量就像是常規的變量,只不過常量的值在定義後不能進行修改。
在 Java 中聲明一個常量每每是在數據類型中定義 final 關鍵字就好了,可是 c 中沒有 final 關鍵字,咱們來看看怎麼定義,以下所示:
整數常量
整數常量能夠是十進制、八進制或十六進制的常量。前綴指定基數:0x 或 0X 表示十六進制,0 表示八進制,不帶前綴則默認表示十進制。
整數常量也能夠帶一個後綴,後綴是 U 和 L 的組合,U 表示無符號整數(unsigned),L 表示長整數(long)。後綴能夠是大寫,也能夠是小寫,U 和 L 的順序任意。
212 /* 合法的 */
215u /* 合法的 */
0xFeeL /* 合法的 */
078 /* 非法的:8 不是八進制的數字 */
032UU /* 非法的:不能重複後綴 */
浮點常量
浮點常量由整數部分、小數點、小數部分和指數部分組成。您可使用小數形式或者指數形式來表示浮點常量。
當使用小數形式表示時,必須包含整數部分、小數部分,或同時包含二者。當使用指數形式表示時, 必須包含小數點、指數,或同時包含二者。帶符號的指數是用 e 或 E 引入的。
3.14159 /* 合法的 */
314159E-5L /* 合法的 */
510E /* 非法的:不完整的指數 */
210f /* 非法的:沒有小數或指數 */
.e55 /* 非法的:缺乏整數或分數 */
定義常量
在 C 中,有兩種簡單的定義常量的方式:
使用 #define 預處理器。
使用 const 關鍵字。
下面是使用 #define 預處理器定義常量的形式:
#define identifier value
例子:
#define name 10L
#define age 27U
void main() {
int person;
person = name + age;
printf("values :%d",person);
}
const 關鍵字
您可使用 const 前綴聲明指定類型的常量,以下所示:
const type variable = value;
例子:
void main() {
const int LEGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
int area;
area = LEGTH * WIDTH;
printf("value of area: %d", area);
}
存儲類定義 C 程序中變量/函數的範圍(可見性)和生命週期。這些說明符放置在它們所修飾的類型以前。下面列出 C 程序中可用的存儲類:
auto
register
static
extern
auto 存儲類
auto 存儲類時全部局部變量默認的存儲類。
int month;
auto int month;
上面定義了兩個帶有相同存儲類,auto 只能用在函數內,即 auto 只能修飾局部變量。
register 存儲類
register存儲類用於定義存儲在寄存器中而不是 RAM 中的局部變量。這意味着變量的最大尺寸等於寄存器的大小(一般是一個詞),且不能對它應用一元的 '&' 運算符(由於它沒有內存位置)。
register int miles;
寄存器只用於須要快速訪問的變量,好比計數器。還應注意的是,定義register並不意味着變量將被存儲在寄存器中,它意味着變量可能存儲在寄存器中,這取決於硬件和實現的限制。
static 存儲類
static存儲類指示編譯器在程序的生命週期內保持局部變量的存在,而不須要在每次它進入和離開做用域時進行建立和銷燬。所以,使用 static 修飾局部變量能夠在函數調用之間保持局部變量的值。static 修飾符也能夠應用於全局變量。當 static 修飾全局變量時,會使變量的做用域限制在聲明它的文件內。
全局聲明的一個 static 變量或方法能夠被任何函數或方法調用,只要這些方法出如今跟 static 變量或方法同一個文件中。
//函數聲明
void func1(void);
static int count = 10; //全局變量 - static 默認的
void main() {
while (count--) {
func1();
}
}
void func1(void) {
// 'thingy' 是 'func1' 的局部變量 - 只初始化一次
// * 每次調用函數 'func1' 'thingy' 值不會被重置。
static int thingy = 5;
thingy++;
printf("thingy 爲 %d, count 爲 %d \n", thingy, count);
}
輸出:
thingy 爲 6, count 爲 9
thingy 爲 7, count 爲 8
thingy 爲 8, count 爲 7
thingy 爲 9, count 爲 6
thingy 爲 10, count 爲 5
thingy 爲 11, count 爲 4
thingy 爲 12, count 爲 3
thingy 爲 13, count 爲 2
thingy 爲 14, count 爲 1
thingy 爲 15, count 爲 0
實例中 count 做爲全局變量能夠在函數內使用,thingy 在局部使用 static 修飾後,不會在每次調用時重置。
extern 存儲類
extern存儲類用於提供一個全局變量的引用,全局變量對全部的程序文件都是可見的。當您使用extern時,對於沒法初始化的變量,會把變量名指向一個以前定義過的存儲位置。
當您有多個文件且定義了一個能夠在其餘文件中使用的全局變量或函數時,能夠在其餘文件中使用extern來獲得已定義的變量或函數的引用。能夠這麼理解,extern是用來在另外一個文件中聲明一個全局變量或函數。
extern 修飾符一般用於當有兩個或多個文件共享相同的全局變量或函數的時候,以下所示:
第一個文件 ndk_day1.c
#include <stdio.h> //stdio.h 是一個頭文件(標準輸入輸出頭文件),#include 是一個預處理命令,用來引入頭文件。
#include "support.h" //引入本身的頭文件
int main() {
int sum = add(2, 5);
printf("extern 使用 :%d", sum);
}
聲明 support.h 頭文件
int add(int num1,int num2){
return num1 * num2;
}
輸出:
extern 使用 :10
運算符是一種告訴編譯器執行特定的數學或邏輯操做的符號。C 語言內置了豐富的運算符,並提供瞭如下類型的運算符:
算術運算符
關係運算符
邏輯運算符
位運算符
賦值運算符
雜項運算符
算術運算符
下表顯示了 C 語言支持的全部算術運算符。假設變量A的值爲 10,變量B的值爲 20,則:
例子:
void main(){
int a = 21;
int b = 10;
int c;
c = a + b;
printf("a + b = %d \n", c);
c = a - b;
printf("a - b = %d \n", c);
c = a * b;
printf("a * b = %d \n", c);
c = a / b;
printf("a / b = %d \n", c);
c = a % b;
printf("a % b = %d \n", c);
c = ++a;
printf("++a = %d , %d \n", c, a);
c = b++;
printf("b++ = %d , %d \n", c, b);
c = b--;
printf("b-- = %d \n", c);
}
輸出:
a + b = 31
a - b = 11
a * b = 210
a / b = 2
a b = 1
++a = 22 , 22
b++ = 10 , 11
b-- = 11
關係運算符
下表顯示了 C 語言支持的全部關係運算符。假設變量 A 的值爲 10,變量 B 的值爲 20,則:
邏輯運算符
下表顯示了 C 語言支持的全部關係邏輯運算符。假設變量 A 的值爲 1,變量 B 的值爲 0,則:
例子:
void main(){
int a1 = 5;
int b1 = 5;
int c1;
//若是兩個操做數都非零,則條件爲真。
if (a1 && b1) {
printf("a1 && b1 %d \n", true);
} else {
printf("a1 && b1 %d \n", false);
}
//若是兩個操做數中有任意一個非零,則條件爲真。
if (a1 || b1) {
printf("a1 || b1 %d \n", true);
} else {
printf("a1 || b1 %d \n", false);
}
//改變 a1 b1 的值
a1 = 0;
b1 = 10;
//若是兩個操做數都非零,則條件爲真。
if (a1 && b1) {
printf("a1 && b1 %d \n", true);
} else {
printf("a1 && b1 %d \n", false);
}
if (!(a1 && b1)) {
printf("!(a1 && b1) %d \n", true);
} else {
printf("a1 || b1 %d \n", false);
}
}
輸出:
a1 && b1 1
a1 || b1 1
a1 && b1 0
!(a1 && b1) 1
位運算符
例子:
void main(){
//位運算符 & | ^ ~
int wA = 60; //0011 1100
int wB = 13; //0000 1101
int wC = 10;
//都爲真,纔是真 0000 1100
printf("wA & wB=?%d\n", wA & wB);
//其中一個爲真,就爲真 0011 1101
printf("wA | wB=?%d\n", wA | wB);
//一個爲真則爲真,2個爲真這爲假 00110001
printf("wA ^ wB=?%d\n", wA ^ wB);
printf("~wB=?%d\n", ~wB);
//二進制左移運算符 左 * 4 = 40
printf("wC<<2=?%d\n", wC << 2);
//二進制右移運算符 右 / 4
printf("wC>>2=?%d\n", wC >> 2);
}
輸出:
wA & wB=?12
wA | wB=?61
wA ^ wB=?49
~wB=?-14
wC<<2=?40
wC>>2=?2
下表顯示了 C 語言支持的位運算符。假設變量 A 的值爲 60,變量 B 的值爲 13,則:
賦值運算符
下表列出了 C 語言支持的賦值運算符:
例子:
void main(){
int wAA = 21;
int wBB;
wBB = wAA;
printf("= %d\n", wBB);
wBB += wAA;
printf("+= %d\n", wBB);
wBB -= wAA;
printf("-= %d\n", wBB);
wBB *= wAA;
printf("*= %d\n", wBB);
wBB /= wAA;
printf("/= %d\n", wBB);
wBB %= wAA;
printf("%= %d\n", wBB);
wBB <<= wAA;
printf("<<= %d\n", wBB);
wBB <<= wAA;
printf(">>= %d\n", wBB);
wBB &= wAA;
printf("&= %d\n", wBB);
wBB ^= wAA;
printf("^= %d\n", wBB);
wBB |= wAA;
printf("|= %d\n", wBB);
}
輸出:
= 21
+= 42
-= 21
*= 441
/= 21
= 0
<<= 0
>>= 0
&= 0
^= 21
|= 21
雜項運算符 sizeof、&、三元
下表列出了 C 語言支持的其餘一些重要的運算符,包括 sizeof 和 ? :。
例子:
void main(){
int zxA = 4;
short zxB;
double zxC;
int *ptr;
//sizeOf 運算符實例 ,lu 32位無符號整數
printf("zxA sizeOf = %lu \n", sizeof(zxA));
printf("zxB sizeOf = %lu \n", sizeof(zxB));
printf("zxC sizeOf = %lu \n", sizeof(zxC));
//& 和 * 運算符實例
ptr = &zxA; //將 zxA 的地址值複製給 ptr 指針
printf("zxA 的值爲:%d \n", zxA);
printf("*ptr 的值爲:%d \n", *ptr);
//三元運算符
zxA = 10;
zxB = (zxA == 1) ? 20 : 30;
printf("zxb 的值爲:%d \n", zxB);
zxB = (zxA == 10) ? 20 : 30;
printf("zxb 的值爲:%d \n", zxB);
}
輸出:
zxA sizeOf = 4
zxB sizeOf = 2
zxC sizeOf = 8
zxA 的值爲:4
*ptr 的值爲:4
zxb 的值爲:30
zxb 的值爲:20
C 語言把任何非零和非空的值假定爲 true,把零或 null 假定爲 false。
C 語言提供瞭如下類型的判斷語句。
?:運算符
跟 Java 同樣
void main(){
int pdNumber;
printf("輸入一個數字:");
scanf("%d", &pdNumber);
(pdNumber % 2 == 0) ? printf("偶數") : printf("基數");
}
C 語言提供瞭如下幾種循環類型。
循環控制語句
循環控制語句改變你代碼的執行順序。經過它你能夠實現代碼的跳轉。
C 提供了下列的循環控制語句。
使用方法能夠參考 Java ,下面給出循環的例子:
void main(){
//限制
for (int i = 0; i < 6; i++) {
printf("限制循環,%d \n",i);
}
//無限循環
for (;;) {
printf("該循環會一直執行下去!\n");
}
}
函數定義
C 語言中的函數定義的通常形式以下:
return_type function_name( parameter list )
{
body of the function
}
在 C 語言中,函數由一個函數頭和一個函數主體組成。下面列出一個函數的全部組成部分:
**返回類型:**一個函數能夠返回一個值。return_type是函數返回的值的數據類型。有些函數執行所需的操做而不返回值,在這種狀況下,return_type 是關鍵字void。
**函數名稱:**這是函數的實際名稱。函數名和參數列表一塊兒構成了函數簽名。
**參數:**參數就像是佔位符。當函數被調用時,您向參數傳遞一個值,這個值被稱爲實際參數。參數列表包括函數參數的類型、順序、數量。參數是可選的,也就是說,函數可能不包含參數。
**函數主體:**函數主體包含一組定義函數執行任務的語句。
例子:
/* 函數返回兩個數中較大的那個數 */
int max(int num1, int num2)
{
/* 局部變量聲明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
函數聲明
函數聲明會告訴編譯器函數名稱及如何調用函數。函數的實際主體能夠單獨定義。
函數聲明包括如下幾個部分:
return_type function_name( parameter list );
針對上面定義的函數 max(),如下是函數聲明:
int max(int num1, int num2);
在函數聲明中,參數的名稱並不重要,只有參數的類型是必需的,所以下面也是有效的聲明:
int max(int, int);
當您在一個源文件中定義函數且在另外一個文件中調用函數時,函數聲明是必需的。在這種狀況下,您應該在調用函數的文件頂部聲明函數。
調用函數
//函數聲明
int max(int num1, int num2);
/**
*C 函數
*/
void main() {
//找出函數中最大值
printf("找出函數中最大值,%d \n",max(66,88));
}
int max(int num1, int num2) {
return (num1 > num2) ? num1 : num2;
}
輸出:找出函數中最大值,88
函數參數
若是函數要使用參數,則必須聲明接受參數值的變量。這些變量稱爲函數的形式參數。
形式參數就像函數內的其餘局部變量,在進入函數時被建立,退出函數時被銷燬。
本節知識將會以分節的形式向你們展現,又想要學習C語言的小夥伴能夠關注筆者!一塊兒來加油呀~
自學C/C++編程難度很大,不妨和一些志同道合的小夥伴一塊兒學習成長!
C語言C++編程學習交流圈子,企鵝羣【1121833361】微信公衆號:C語言編程學習基地
有一些源碼和資料分享,歡迎轉行也學習編程的夥伴,和你們一塊兒交流成長會比本身琢磨更快哦!