1972年Dennis Ritchie發明了C語言,而後Dennis Ritchie又使用C語言重寫了Unix系統,自那以後C語言逐漸受到了全世界大多數編程愛好者的喜愛,後期的主流操作系統Linux,MacOSX,Windows的絕大部分底層都是采用C語言來實現的,主流編程語言Java,PHP,Python的底層也是C語言實現的。
而伴隨著移動互聯網(Android,IOS),雲計算,大數據以及物聯網的不斷發展,C語言會占據更加廣闊的市場,因此C語言是作為一名ITMan必須深入掌握的語言。
2016年4月 TIOBE 編程語言排行榜(前20名)
計算機通常都是由硬件和軟件組成的,其中硬件主要包含CPU,內存,硬盤和網卡以及IO設備組成。
程序是運行在計算機硬件之上的,那麼計算機硬件是由哪些部分組成的呢?
計算機硬件主要包含CPU,內存,硬盤和網卡以及IO設備組成
下面簡要介紹下各個組件之間的作用:
CPU主要是用來計算數據和控制各個硬件設備協助完成數據輸入輸出等等
內存主要是用來臨時存儲運算的(少量)數據,斷電後數據會丟失
硬盤主要是用來永久存儲大容量(TB)的數據
網卡用於在網絡上傳輸數據
IO設備在CPU的控制下完成數據輸入(通常是鼠標鍵盤完成)以及輸出(通常是聲卡,顯卡或者打印機完成)
在程序故障診斷時通常都需要考慮單機的CPU,內存和磁盤以及網卡的性能瓶頸
軟件的出現實現了人與計算機之間更好的交互方式。
軟件分類主要分成系統軟件和應用軟件兩種,其中系統軟件有基於命令行交互方式,運行於服務器端的Unix(Solaris13),Linux(Redhat7.0),基於圖形化界面,運行於PC,筆記本上的Ubuntu16,Windows10,MacOSX10.11,基於語音手勢識別,觸控滑動,運行於移動終端(手機,電視,嵌入式設備)的Android和IOS等主流操作系統,其中Android是基於Linux發展而來,IOS是基於MacOSX發展而來。
應用軟件主要是運行在PC或者是移動終端的操作系統之上,用於解決生活的各種需求,例如購物,聊天,聽音樂,看電影,收發郵件等等,例如,天貓京東支付寶,微信,天天動聽,迅雷影音,FoxMail等等。
而目前主流技術趨勢是基於Android和IOS的移動互聯網以及將來(5-10年後)即將火爆的物聯網
程序就是指令系統加上數據集 組成,而每個CPU都有自己的指令系統(由二進制的機器碼010101序列組成),PC上一般是X86指令系統,手機上是ARM指令系統,這也就意味著PC上的程序不加修改就不能到手機上運行,手機上的程序不加修改也不能到PC上運行,這也就是最早的編程語言-機器語言的由來,它的特點是高效,不能移植,不易開發和後期維護等等。
斗轉星移,匯編語言和編譯器的出現解決了需要記住非常多的機器指令的難題,但是還是沒有從根本上解決移植性的問題,只是將機器指令轉換為易懂的英文單詞,然後由編譯器編譯成機器指令,因為計算機終歸揭底智能識別0001110100110機器指令,而且匯編語言是面向機器的,不同機器的匯編指令是不相同的。
這裡的代碼是演示Windows上將匯編語言嵌套在C語言中使用,完成兩個變量相加的結果
void use_asm(){
int a, b, c=0;
a = 4;
b = 6;
printf("a = %d \t b=%d\tc=%d \n",a,b,c);
_asm{
mov eax, a;
add eax, b;
mov c ,eax;
}
printf("a = %d \t b=%d\tc=%d\n", a, b, c);
}
void main(){
use_asm();
getchar();
}
時光再流轉,在1972年C語言的誕生,一種以面向過程,高效和可移植性的編程語言,C語言的出現,屏蔽了底層硬件的不同,使得開發人員可以集中精力在業務邏輯的實現上,適合做系統軟件,驅動程序的開發,同時它也存在著對系統平台庫的嚴重依賴,只有標准C的部分是可移植(所有的主流操作系統都實現了C語言的標准庫函數),軟件實現周期較長等缺點。而後期的C++,Java,C#,Python,PHP等編程語言在很多方面都吸收了C語言的優點,新增了如面向對象(OO),更加完善的API接口以及提供了日常開發中所需的豐富的類庫等諸多的特性,更加適合做應用軟件開發。
目前流行的NoSQL數據庫Redis就是采用標准C開發的,而MongDB是采用C++語言開發的。
由C語言編寫的程序可以運行在各大主流操作系統之上,而且標准C的部分是可移植的。而且為了方便開發人員開發,測試和部署應用程序等,還提供了強大的集成開發環境,在C語言學習初期可以采用Windows10+VisualStudio2015的C語言環境,後面的博文將會使用VisualStudio2015(後面都會簡稱為VS2015)作為開發C語言的IDE,在講到C語言的平台差異性時會使用Linux系統的VIM編輯器(該編輯器只能寫簡單的C程序)。
下面是各大主流操作系統對應的IDE
操作系統
IDE
Windows10
VisualStudio2015
Linux(Ubuntu16)
QT5.5
MacOSX10.11/IOS9
XCode7.2
Android6
AndroidStudio2.0
除此之外還有些跨平台的IDE,例如CodeBlocks,Eclipse等等。讀者們可以根據自己的喜好以及平台來選擇對應的IDE。
helloworld程序通常是學習一門語言的入門程序,如果能夠正常編譯運行helloworld,就表示編譯和運行環境已經搭建完成。
VS2015安裝時可以選擇指定的模塊安裝,我的機器是i5+12G內存,安裝所有的模塊大概耗時6個小時,使用VS2015還可以開發Anndroid IOS程序。
安裝完成之後需要使用Microsoft公司的賬號登錄之後才能免費使用,這裡提供一個企業版的激活碼:HM6NR-QXX7C-DFW2Y-8B82K-WTYJV,過了免費的時間之後可以使用該激活碼激活。
送上啟動界面:
可以使用Ctrl+Shift+N快捷鍵實現創建一個新的工程
點擊確定之後就會看到如圖所示的內容了:
下面對該項目的目錄結構做一個說明:
VS2015有個解決方案的概念,一個解決方案下面可以存在多個項目,例如這裡已經創建了一個和解決方案同名的項目WindowsC,該項目下有兩個重要的目錄,分別是頭文件和源文件,頭文件用於存放函數聲明,源文件就是存放開發人員編寫代碼的目錄了。
需要注意的是同一個解決方案下不能存在相同名字的源文件,當一個解決方案下存在多個項目時如果要運行指定的項目,需要將其設為啟動項後運行,而且同一個項目項目只能有一個main函數,否則無法編譯通過
helloworld的本質就是在控制台上打印一串字符串,windows的命令行下可以使用echo命令實現類似的功能。
而要使用C語言完成這個功能則需要借助於printf函數來實現,而要想使用該函數,必須使用#include
#include <stdio.h>//引入位於系統路徑(C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt)標准輸入輸出頭文件
#include <stdlib.h> //引入位於系統路徑(C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt)標准庫函數頭文件
頭文件編寫完成之後就可以編寫源文件用於實現helloworld了
helloworld源碼實現:
#include "common.h"
/*
定義程序主入口
@author Tony [email protected]
@since 2016-05-12 19:26
*/
void main() {
printf("Hello World \n");
system("echo Hello World Again\n");
system("pause");
return;
}
HelloWorld源程序解析
#include "common.h" //包含共通的頭文件,會將頭文件的內容替換到HelloWorld.c源文件中 當需要包含系統路徑下的頭文件時使用<>
/*
每個C程序要想運行,必須定義一個入口點,即main方法,方法的參數可以為空
Windows平台的編譯器規定main方法的返回值為空
Linux平台的編譯器規定main方法的返回類型為int
@author Tony [email protected]
@since 2016-05-14 19:32
*/
void main() {
printf("Hello World \n");//打印字符串Hello World並換行
system("echo Hello World Again\n");//調用系統的echo命令輸出指定的字符串
system("pause"); //程序暫停,輸入任意鍵程序會退出
return; //返回為空 return之後的語句都不會執行!
}
上述代碼中使用了C語言的兩種注釋,分別是單行注釋和多行注釋,注釋是描述程序的意圖,方便後期維護,編譯器會刪掉注釋的內容,而不影響程序的邏輯。
編寫完成helloworld之後就是運行程序觀察執行結果了,當然這中間包括了非常復雜的過程,後續博文會詳細講解背後的原理,現在只要按下F5就可以觀察到如下的運行結果了。
在使用VS2015編寫helloworld的源代碼以及相關的頭文件時,使用其提供的快捷鍵F5編譯並運行了程序,但這背後實際上還包含了預編譯,轉匯編,編譯,鏈接四個步驟。
接下來將采用Linux(CentOS7)操作系統的C語言環境結合GCC編譯器的一些編譯選項來解剖C語言的運行原理。
環境說明:
宿主機操作系統:Windows10 企業版
虛擬機:CentOS7 企業版
編輯器:gedit
SSH遠程連接工具:XShell,XManager
[root@tony Desktop]# cd /home/guanglei/Desktop/ #進入桌面
[root@tony Desktop]# gedit helloworld.c #使用gedit編輯c語言的源文件
helloworld.c源代碼如下:
#include "common.h"
#include <stdio.h>//引入跨平台的標注輸入輸出頭文件
#include <stdlib.h> //引入跨平台的標准庫頭文件
/*
定義程序主入口
@author Tony [email protected]
@since 2016-05-14 19:45
*/
int main(){
printf("This program is running CentOS7 \n!!!");
system("date"); //顯示當前系統日期
system("ps -ef|grep java");//查看運行的java進程
return 0;// 返回0表示正常退出
}
使用gedit編輯helloworld.c效果示意圖:
編寫完源碼之後就可以使用Linux(CentOS7)提供的gcc編譯器來編譯源程序了。
第一步 預編譯
預編譯就是將include包含的頭文件的內容替換到源文件中,同時將代碼中注釋的內容刪除,使用gcc編譯器的-E選項實現預編譯:
[root@tony Desktop]# gcc -E helloworld.c -o helloworld.e #-o表示輸出的文件名稱
[root@tony Desktop]# gedit helloworld.e #使用geit查看預編譯後的結果
第二步 轉匯編
C語言的源代碼計算機是不能識別的,因此在運行之前需要將其轉換成匯編語言,可以通過gcc編譯器的-S選項來實現轉換成匯編:
[root@tony Desktop]# gcc -E helloworld.c -o helloworld.e
第三步 編譯
計算機只能識別二進制的機器碼,編譯器會將匯編指令轉換成二進制的機器碼,可以使用gcc編譯器的-c選項來實現轉換成二進制:
[root@tony Desktop]# gcc -c helloworld.c -o helloworld.o #編譯成二進制
第四步 鏈接
在編譯成機器碼之後程序還不能夠直接運行,還需要一個鏈接的過程,就是將C語言庫函數以及源碼轉換後的二進制文件打包到一起組成可執行的文件。
這些步驟可以一次實現(預編譯,編譯和鏈接)
[root@tony Desktop]# gcc -o helloworld.o helloworld.c
[root@tony Desktop]# ./helloworld.o #運行改程序並顯示結果
This program is running CentOS7
Wed May 11 22:33:05 PDT 2016
root 6208 6206 0 22:33 pts/0 00:00:00 sh -c ps -ef|grep java
root 6210 6208 0 22:33 pts/0 00:00:00 grep java
Windows系統包含大量的系統命令,提供了日常使用的絕大部分功能,實際上Windows系統圖形化界面操作的背後就是在調用這些系統命令,學會這些常用的命令可以讓我們更加方便和快捷的使用Windows系統提供的功能。
要想使用命令,必須啟動一個cmd命令窗口,使用Windows+R,輸入cmd後即可啟動命令行窗口,
cmd運行示意圖:
當看到如上圖所示的命令行界面之後就可以輸入Windows提供的命令來完成日常絕大部分操作的功能了。
下面將介紹常用的Windows命令行提供的指令
文件管理命令集
dir #列出當前目錄列表
md #創建目錄
rd #刪除目錄
cd #進入指定的目錄(windows只能在當前盤符下切換)
del #刪除文件
exit #退出cmd命令行
type #顯示文件內容
實用程序和系統管理命令集
calc #計算器
notepad #記事本
mspaint #畫圖
timedate.cpl #日期和時間
cleanmgr #磁盤清理工具
CompMgmtLauncher #計算機管理
desk.cpl #屏幕分辨率
perfmon #計算機性能檢測器
powercfg.cpl #電源選項
regedit #注冊表編輯器
shutdown -s
services.msc #本地服務設置
Msconfig #系統配置
msinfo #系統信息
mstsc #遠程連接
explorer #資源管理器
firewall.cpl #防火牆
taskkill /f /im process.exe #關閉指定的進程
appwiz.cpl 程序和功能(添加或者卸載程序)
control 控制面板
除了在cmd命令行窗口調用這些程序之外,C語言提供了一個位於stdlib.h頭文件的system函數來調用各大操作系統(Windows,Linux,MacOSX,Android,IOS都可以)。
使用system函數調用Windows命令示例:
共通的頭文件
#define _CRT_SECURE_NO_WARNINGS//關閉VS2015的安全檢查
#include <stdio.h>//引入位於系統路徑(C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt)標准輸入輸出頭文件
#include <stdlib.h> //引入位於系統路徑(C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt)標准庫函數頭文件
#include <Windows.h> //引入Windows頭文件
源代碼
#include "common.h"
/*
根據傳遞的命令字符串調用系統命令
*/
void call_system(char str[]) {
printf("你輸入的要執行的命令是%s\n", str);
system(str);
}
/*
程序主入口
@author Tony [email protected]
@since 2016-05-14 09:40
*/
void main() {
char str[100] = { 0 }; //定義一個字符數組 數組中的每個元素初始化為0
printf("請輸入system函數調用windows系統命令的名稱\n");
scanf("%s", str); //將輸入的命令字符串賦值給str
call_system(str);
call_system("pause");
}
使用Windows系統庫函數ShellExecuteA函數實現異步打開和關閉程序
共通的頭文件
#define _CRT_SECURE_NO_WARNINGS//關閉VS2015的安全檢查
#include <stdio.h>//引入位於系統路徑(C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt)標准輸入輸出頭文件
#include <stdlib.h> //引入位於系統路徑(C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt)標准庫函數頭文件
#include <string.h> //引入字符串頭文件
#include <Windows.h> //引入Windows頭文件
#include "common.h"
/*
根據傳遞的字符串執行system函數調用系統命令
@author Tony [email protected]
@since 2016-05-14 09:29
*/
void start_process(char str[]) {
printf("你輸入的要執行的命令是%s\n",str);
char execute_str[100] = {0};
strcpy(execute_str, "start ");
ShellExecuteA(0,"open",str,0,0,1); //異步執行打開指定的進程
}
/*
關閉指定的進程
*/
void kill_process(char str[]) {
printf("你要終止的進程名稱為%s\n",str);
char kill_str[100] = { 0 };
strcpy(kill_str,"start ");
strcat(kill_str, "taskkill /f /im ");
strcat(kill_str,str);
strcat(kill_str, ".exe");
printf("執行結束進程的字符串內容是%s",kill_str);
system(kill_str);
}
/*
定義程序主入口
@author Tony [email protected]
@since 2016-05-14 09:26
*/
void main() {
char str[100] = {0}; //定義一個字符數組 數組中的每個元素初始化為0
printf("請輸入system函數調用windows系統命令的名稱\n");
scanf("%s",str); //將輸入的命令字符串賦值給str
start_process(str);
Sleep(5000); //程序此處會暫停5S
kill_process(str);
system("pause");
}
歡迎掃描下方的二維碼,關注微信公眾服務號-藝無止境,分享IT技術干貨。