架構師成長之道-C語言基礎之C語言概述

 架構師成長之道-C語言基礎之C語言概述

1.1 信息技術發展趨勢

目前信息技術主要經歷了互聯網、移動互聯網以及以大數據、雲計算、物聯網、人工智能、區塊鏈爲表明的新興技術三個階段。php

  • 互聯網
    互聯網從20世紀90年代逐漸興起,主要是經過網絡鏈接了世界各地的筆記本、臺式機以及背後提供後臺數據服務的服務器集羣,其中絕大多數筆記本和臺式機都運行着Windows,macOS系統,而服務器主要是以類Unix(CentOS,Ubuntu)佔據主要市場,依靠互聯網成長起來的公司有微軟、谷歌、蘋果、亞馬遜、百度、阿里巴巴、騰訊等等。html

  • 移動互聯網
    移動互聯網主要是經過網絡鏈接了世界各地的移動設備(最典型的就是手機),它們絕大多數都運行着Android,IOS系統,依靠移動互聯網公司成長起來的有美團、滴滴、小米、螞蟻金服,最近(2019/08)華爲發佈了鴻蒙操做系統。linux

  • 雲計算、大數據
    固然隨着用戶數據的爆發式增加,以海量數據爲基礎的大數據、雲計算技術在BAT,Apple,Microsoft,Amazon,Google級別的超大型互聯網公司有普遍的應用場景。c++

  • 物聯網
    物聯網會以手機爲中樞,經過網絡鏈接全部智能設備,包括智能家居、汽車、電視等嵌入式設備,目前小米,華爲等大廠在智能家居,電視開始佈局。git

  • 人工智能
    人工智能(AI)做爲當前最火爆的技術之一,國內的BAT紛紛開始根據自身核心業務佈局,阿里巴巴最先將人工智能應用在電商和物流領域,而百度開發出了對話時人工智能操做系統Dueros和自動駕駛平臺Apollo,而騰訊則是在遊戲領域應用人工智能。程序員

  • 區塊鏈
    而區塊鏈經歷了數字貨幣、智能合約、和超級帳本三個發展階段,區塊鏈技術能夠普遍使用在金融、供應鏈、物流、公共服務領域,解決互聯網的信任問題。
    目前螞蟻金服、京東已經有大量的區塊鏈應用落地。github

1.2 淺談計算機系統架構

1.2.1 計算機硬件系統

現代計算機是由運算器、控制器、存儲器、輸入設備、輸出設備五大部分組成,它們各司其職,完成了數據的計算、存儲、傳輸任務。shell

  • CPU
    也被稱爲中央處理器,由運算器和控制器組成,其主要做用是數據計算(從內存中獲取指令並執行後將結果返回給內存或者寫入到磁盤)和控制其餘設備(聲卡顯卡,鼠標鍵盤)協同工做。目前主流的CPU架構有基於Intel的複雜指令集的X86架構(32位和64位)和手機(ARM指令集),服務器(SPARC指令集)的精簡指令集。CPU經過總線(數據總線、地址總線、控制總線)和外部進行交互。
  • 內存
    採用編址存儲,其主要做用是用來做爲程序的工做區,程序運行時其數據和指令會被加載到內存,斷電後數據會丟失。
  • 硬盤
    其主要做用是永久性存儲海量數據,分爲機械式硬盤和固態硬盤兩大類。
  • IO設備
    其主要做用是用來數據的輸入輸出,常見的輸入設備包括鼠標鍵盤,常見的輸出設備包含聲卡,顯卡,打印機等等。網卡主要是負責數據在網絡上的傳輸。
    在後期程序排錯時除了考慮程序自己的錯誤以外還要考慮計算機硬件故障(例如磁盤被寫滿,網絡不通)等問題。

每一個計算機組件的IO性能也各不相同,核心組件(CPU,內存,磁盤)都遵循容量越大,IO性能越差,以下圖所示,彙總了它們的IO性能。數據庫

 

IO性能彙總
IO性能彙總

 

在後期程序優化時,一般須要考慮時間複雜度和空間複雜度的問題。編程

1.2.2 計算機軟件系統

軟件出現的做用是實現了人和計算機更好的交互,它是由開發人員採用某種編程語言來編寫一系列的指令以及根據不一樣的業務邏輯產生的數據組成。

1.2.2.1 軟件分類

而軟件一般被分爲系統軟件和應用軟件

  • 系統軟件:
    系統軟件有運行在服務器端的Unix,Linux,運行在PC桌面的macOS,Windows;運行在移動設備(手機、電視)的Android,IOS;系統軟件一般是負責管理硬件資源,同時給應用軟件提供運行平臺。

  • 應用軟件:
    應用軟件有運行在PC桌面、手機端的淘寶、京東、微信、支付寶等等。

1.2.2.2 軟件的交互方式

不一樣平臺的軟件有不一樣的交互方式:

  • 服務器端:
    運維開發人員基於命令行的字符界面實現人機交互。
  • PC桌面端:
    開發人員、設計人員、產品經理、普通用戶一般是基於圖形化界面實現人機交互。
  • 移動端:
    普通用戶一般是經過語音,手勢觸控實現人機交互。

1.2.3 經常使用應用的軟硬件協做實現

計算機程序運行流程以下圖所示
計算機程序運行流程

  • 聊天:應用程序監聽鍵盤輸入的數據,放到內存,而後傳給網卡,經過網絡傳遞給另一個網卡,再從網卡傳到內存,顯示在顯示器上。
  • 聽音樂:應用程序將音樂數據加載到內存以後,而後寫到聲卡上。
  • 看視頻:應用程序將視頻數據加載到內存,而後寫到顯卡上。
  • 讀文檔: 應用程序將磁盤中的文檔數據加載到內存後顯示到屏幕上。
  • 寫文檔: 應用程序將內存中的數據寫入到磁盤上。

1.3 程序和指令

  • 程序:
    程序是爲了完成某項特定任務(例如聊天,聽音樂等等)而使用某種編程語言編寫的一組指令序列。
  • 指令:
    指令是對計算機進行程序控制的最小單位,由操做碼和操做數組成,操做碼指的是機器要執行什麼操做(例如加減乘除),而操做數就是具體執行的對象(具體的數據以及存放數據的位置),全部指令的集合稱爲計算機的指令系統,常見的電腦指令系統有Intel X86指令集,常見的手機指令系統有ARM。所以手機上的應用程序不加修改是不能在電腦上直接運行,由於不一樣的指令集是不兼容的。

1.4 編程語言發展史及其應用場景

1.4.1 編譯器與高級語言

首先明確一點,計算機最底層只能識別二進制(010101)的機器指令,那些由彙編語言或者是高級程序設計語言編寫的應用程序只是爲了方便開發人員理解和維護,這就須要將彙編語言和高級語言翻譯成計算機可以理解的機器語言,而編譯器或者解釋器就是作這個工做的。它的出現讓開發人員在編寫程序時不用考慮底層硬件的差別性,只須要專一具體業務邏輯的實現便可。

C語言的編譯器在各個操做系統之上都有實現,其中Windows系統可使用Visual C編譯器,而Linux可使用GCC編譯器,macOS可使用LLVM CLang編譯器。

1.4.2 編程語言發展史

任何事物都是從無到有,逐步發展壯大起來的,編程語言也是同樣。

計算機程序設計語言經歷了機器語言到彙編語言和高級程序設計語言三個階段,其特色是使得程序員用編程語言開發、測試、部署應用程序愈來愈方便、高效。可是是以犧牲效率爲代價,可是隨着計算機硬件的發展,絕大多數應用場景的效率損失能夠忽略不計。

  • 機器語言
    計算機發展的最先期,程序員編寫程序採用二進制的指令(010010101)來實現的,而每種CPU都有各自不一樣的指令系統(Ultra SPARC/Intel X86/ARM),所以在不一樣的機器上使用不一樣的機器語言實現。其特色是性能特別高效,而面向機器編程也就意味着不能移植,須要手動處理底層硬件的差別性,並且二進制的指令難以理解和維護。
  • 彙編語言
    隨着時代和計算機技術的發展,彙編語言和編譯器的出現解決了機器語言須要記住很是多的二進制機器指令的難題,可是仍是沒有從根本上解決移植性的問題,只是將機器指令轉換爲易懂的英文單詞,而後由編譯器編譯成機器指令,由於計算機終歸揭底只能識別二進制的0001110100110機器指令,並且彙編語言是面向機器的,不一樣機器(SPARC/Intel X86/ARM)的彙編指令是不相同的。
  • 高級程序設計語言
    高級程序設計語言的高級之處體如今開發人員在編寫程序時無需關心計算機底層硬件差別而只須要專一於業務模塊實現便可。甚至是能夠實現 一次編譯,處處運行,這裏以Java爲例子:經過實現不一樣平臺的JVM,編譯生成的字節碼文件能夠在任意的JVM上運行。
    高級語言一般都須要編譯器或者是解釋器將源碼編譯或者解釋後執行。
    高級語言主要分爲面向過程和麪向對象兩種,其中典型的面向過程編程語言就是C,面向對象的編程語言有Java,C++等等。

1.4.3 編程語言應用場景

若是想知道目前主流的編程語言有哪些,能夠訪問tiobe 首頁獲取編程語言排行榜。

2019年8月編程語言排行榜Top20
Tiboe編程語言排行榜

根據Tiobe排行榜得知,Java/C/Python分別排在前三名, 隨後緊跟着C++,C#等等.

每種語言都有不一樣的應用場景和擅長的領域。

編程語言 應用場景
C 硬件驅動、操做系統、系統軟件
C++ 系統軟件、網絡通信、科學計算 、遊戲
C# Windows應用,Web應用、遊戲
Java 大型互聯網應用(淘寶、天貓),Android,大數據
Python 人工智能、機器學習、自動化運維、數據分析 、圖形處理
PHP 中小型網站開發
Objective-C/Swift macOS,iPhone,iPad應用開發
JavaScript 瀏覽器端、服務端、PC桌面
Go 高併發、區塊鏈

那麼若是你做爲初學者,面對如此之多的編程語言,到底應該先從哪門語言上車呢?若是你想深刻的學習其餘語言和架構相關的知識以前建議熟練掌握C語言。由於C++/Java/C#等編程語言都模仿了C語言。不管哪一種語言,都是實現目標的工具,而不是目標自己。

1.5 C語言概覽

C語言憑藉其高效率、良好的移植性、功能強大的特性在操做系統、硬件驅動以及系統應用開發佔據廣闊的市場。

1.5.1 C語言發展簡史

 

Dennis Ritchie
Dennis Ritchie

 

  • 起源
    1972年,貝爾實驗室的Dennis Ritchie和Ken Thompson在開發Unix操做系統時設計了C語言,該操做系統的90%以上的代碼都是由C語言實現,後期的Linux,MacOS,Android,IOS都是基於Unix發展而來的。
  • 標準
    1987年Dennis Ritchie和Brian Kernighan編寫了The C Programming Language初版是公認的C標準實現,而沒有定義C庫。
    然後期ANSI/ISO前後於1990年、1999年和2011年發佈了C90標準、C99標準和C11標準,該標準定義了C語言和C標準庫。

1.5.2 C語言特性

C語言做爲面向過程的高級程序設計語言,可以輕鬆的實現自頂向下的規劃、結構化編程和模塊化設計,這樣使得程序結構更加簡潔,可擴展性強以及更加容易維護。

並且C語言有着高效(執行速度快)、功能強大(嵌套匯編)以及可移植性(標準庫可移植)、功能強大等優勢,並且也存在着對系統平臺庫依賴嚴重,因爲編程風格自由,經驗不足也會容易致使出錯,編寫代碼實現週期長,一樣的代碼在不一樣的操做系統(或者編譯器)下可能會有不一樣的表現等缺點。

1.5.3 C語言應用場景

C語言偏向操做系統、硬件驅動、底層應用(數據庫、編譯器)、嵌入式應用開發、遊戲引擎等應用場景。

  • 硬件驅動的絕大部分實現是由C語言和彙編語言實現的。
  • 主流操做系統(Unix,Linxu,MacOS,Windows,Android,iOS)的底層實現都是由C語言和部分彙編實現的。
  • C++,Java,Python,Swift的編譯器或者解釋器都是由C語言實現的。
  • Git,Nginx,Redis,MySQL都是使用C語言實現的,並且都是開放源代碼的,能夠在GitHub中獲取到,能夠經過閱讀源碼提高本身的設計和編碼能力。

1.6 C語言集成開發環境搭建

目前主流操做系統(Windows,Linux,MacOS)都有完善的C語言集成開發環境,用於編輯、編譯、調試、打包部署C程序。

操做系統 開發工具
Windows10 Visual Studio2019
macOS10.14 XCode10.3
Ubuntu18.04 QT5.13

Windows做爲世界上最流行的桌面操做系統,最新版本爲Windows10 1903,VisualStudio做爲Windows上最強大的集成開發環境,能夠開發Windows軟件,遊戲,Web應用等等,最新版本爲VisualStudio2019 16.2.2。
Visual Studio 2019啓動界面

Ubuntu做爲最受歡迎的桌面版Linux系統之一,推薦採用跨平臺的集成開發環境QT來編寫C/C++程序。
QT Creator

MacOS平臺推薦使用XCode來編寫C/C++程序,並且XCode在macOS系統上是自帶的,無需額外安裝。
Xcode

除此之外還有些跨平臺的C/C++ 開發工具,例如來自Jetbrains公司的CLion也能夠用來編寫C/C++程序。
Clion

關於IDE的安裝以及使用,它們的官網都提供了詳細的教程,同窗們能夠自行去查閱。

IDE 官網地址
Visual Studio 下載 文檔
CLion 下載 文檔
QT 下載 開發者
XCode 官網

C語言學習過程當中會使用Windows10 1903+Visual Studio 2019做爲主力開發工具,若是沒有特別的說明,默認的環境就是Windows10 1903和Visual Studio 2019。

1.7 Visual Studio Code實現HelloWorld

HelloWorld是學習一門編程語言的入門程序,若是你能獨立編寫並運行HelloWorld,那麼就意味着邁入了編程的大門了。

Visual Studio Code是微軟推出的一款開源、跨平臺編輯器,這裏使用它來編寫C語言的源代碼,若是想了解Visual Studio Code更多內容,能夠去官網拜讀文檔。

爲何首先要使用Visual Studio Code來編寫第一個C程序呢,由於Visual Studio Code只是一個編輯器,用於編寫源碼,並不提供編譯或者解釋運行程序的功能。經過它來對比IDE,體驗下使用IDE開發程序帶來的好處,也有利於理解IDE背後的機制。

  1. 在D盤的code目錄下建立源文件helloworld.c,C語言的源文件都是以.c結尾的。
  2. 編輯源文件
#include <stdio.h>

int main(int argc, char* argv[]) {
    printf("Hello World Windows10 1903 & Visual Studio Code & C ");
    return 0;
}
  1. 編譯源文件
    將源文件編譯成對應平臺的可執行程序,由於計算機不能識別開發人員編寫的源文件內容,只能識別二進制的機器指令。而C語言編寫的源程序可使用多種編譯器來編譯:Windows系統能夠安裝QT或者Visual Studio 2019後編譯源文件

QT中自帶了GCC編譯器,以QT5.13爲例,將QT的默認安裝路徑(C:\Qt\Qt5.13.0\Tools\mingw730_64\bin) 添加到系統的PATH環境目錄下

而後在Windows命令行的終端中輸入gcc -v,看到相似以下輸出,就可使用gcc編譯器了

C:\Users\ittim>gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=C:/Qt/Qt5.13.0/Tools/mingw730_64/bin/../libexec/gcc/x86_64-w64-mingw32/7.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-7.3.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --enable-libstdcxx-filesystem-ts=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/include -I/c/mingw730/prerequisites/x86_64-zlib-static/include -I/c/mingw730/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/include -I/c/mingw730/prerequisites/x86_64-zlib-static/include -I/c/mingw730/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/include -I/c/mingw730/prerequisites/x86_64-zlib-static/include -I/c/mingw730/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/lib -L/c/mingw730/prerequisites/x86_64-zlib-static/lib -L/c/mingw730/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
gcc version 7.3.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)

gcc編譯源文件並運行生成的可執行文件

D:\code>dir
 驅動器 D 中的卷是 DATA
 卷的序列號是 B0FB-1B0A

 D:\code 的目錄

2019/08/18  10:48    <DIR>          .
2019/08/18  10:48    <DIR>          ..
2019/08/18  10:46               159 helloworld.c
               1 個文件            159 字節
               2 個目錄 205,122,088,960 可用字節

D:\code>gcc helloworld.c -o helloworld.exe

D:\code>helloworld.exe
Hello World  Windows10 1903 & Visual Studio Code & C

Visual Stuido 2019只須要在路徑C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2019\Visual Studio Tools下運行 Developer Command Prompt for VS2019後 使用cl命令編譯源文件命令便可。

 

Visual Studio 2019編譯運行C程序
Visual Studio 2019編譯運行C程序

 

**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.2.2
** Copyright (c) 2019 Microsoft Corporation
**********************************************************************

C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise>d:

D:\>cd code

D:\code>cl helloworld.c
用於 x86 的 Microsoft (R) C/C++ 優化編譯器 19.22.27905 版
版權全部(C) Microsoft Corporation。保留全部權利。

helloworld.c
Microsoft (R) Incremental Linker Version 14.22.27905.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:helloworld.exe
helloworld.obj

D:\code>helloworld.exe
Hello World  macOS & Visual Studio Code & C

1.8 Visual Studio 2019集成GitHub

在正式使用Visual Studio 2019開發C語言的程序時,能夠集成GitHub插件,編譯後期代碼統一管理。

Github是開源的項目託管平臺,在使用它以前得先建立一個帳號。後續全部的C程序的源文件都會上傳到GitHub,這樣即便更換電腦,只須要從遠程的GitHub將項目克隆到本地便可。

  1. 啓動Visual Studio 2019
    繼續,但無需代碼

  2. 下載Visual Studio 的GitHub插件
    點擊Visual Studio菜單 擴展->管理擴展
    管理擴展
    而後點擊聯機,選擇GitHub Extension for Visual Studio 點擊下載便可。
    下載插件

  3. 安裝GitHub插件
    在Visual Studio 2019中下載完GitHub插件之後須要手動關閉Visual Studio 2019,而後會自動開啓安裝進程
    用戶帳戶控制
    用戶帳戶控制
    此時Visual Studio會去聯網下載GitHub插件,若是遇到網絡緣由下載超慢,能夠掃描下方的二維碼下載
    GitHub

而後關閉VisualStudio2019,進入C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE目錄下
而後進入目錄
輸入cmd
輸入cmd
此時就已經進入C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE目錄下,只須要輸入VSIXInstaller.exe C:\Users\ittim\Desktop\GitHub.VisualStudio.vsix並回車後即可開始安裝GitHub插件
執行安裝

開始安裝
Install

安裝完成
安裝完成

  1. 鏈接GitHub
    GitHub插件安裝完成之後,重啓Visual Studio 2019
    重啓Visual Studio 2019

首先將項目由解決方案資源管理器切換到團隊資源管理器,而後點擊鏈接GitHub
鏈接GitHub

  1. 登陸GitHub
    輸入用戶名和密碼登陸GitHub
    登陸GitHub

  2. 建立倉庫
    首先點擊建立菜單
    建立倉庫
    而後設置倉庫名稱、描述以及本地倉庫路徑、Git忽略、License
    設置項目信息

若是一切順利,可使用瀏覽器訪問地址https://github.com/ittimeline/c-core-programming 來訪問項目,各位同窗只須要將ittimeline替換成大家的帳戶便可。
c-programming

1.9 Visual Studio 2019實現HelloWorld

  1. 新建解決方案
    在以前建立的Git倉庫c-core-programming基礎上新建項目
    新建解決方案
    而後選擇項目模板:基於C++的空項目
    基於C++的空項目
    而後設置項目名稱、路徑以及解決方案名稱
    配置新項目

  2. 新建篩選器
    在解決方案資源管理器視圖下,選中源文件,而後新建篩選器
    新建篩選器
    篩選器的名稱爲Chapter1
    Chapter1

  3. 新建項
    新建項
    新建源文件helloworld.c
    helloworld.c

  4. 編輯源文件

#include <stdio.h>
#include<stdlib.h>

int main(int argc, char* argv[]) {
    printf("Windows10 1903 & Visual Studio 2019 Hello World \n");
    system("pause");
    return 0;
}
  1. 運行helloworld
    點擊本地Windows調試器,能夠運行程序,也能夠經過快捷鍵F5啓動本地Windows調試器來運行程序
    本地Windows調試器
    程序運行結果
    程序運行結果
    若是想要關閉程序,能夠經過快捷鍵Shift+F5實現。

若是運行程序時出現以下提示
在調試時中止自動關閉控制檯
能夠根據提示設置在調試時中止自動關閉控制檯
在調試時中止自動關閉控制檯

Visual Studio遇到printf()語句自動彈出終端輸出Windows10 1903 & Visual Studio 2019 Hello World,遇到return語句關閉終端,打開終端和關閉終端時間很短,感受程序有閃退現象。
這裏能夠調用stdlib.h頭文件中的system函數並傳遞字符串參數pause讓程序暫停。

  1. 推送代碼到遠程倉庫
    首先切換到團隊資源管理器視圖下,而後點擊更改
    更改
    而後填寫提交信息,點擊所有提交,此時會將代碼提交到本地倉庫
    commit log
    而後點擊同步到遠程倉庫
    同步遠程倉庫
    推送到遠程倉庫
    推送到遠程倉庫

而後就能夠在GitHub倉庫中查看提交的內容
github/ittimeline/c-core-programming

1.10 HelloWorld詳解

1.10.1 #include預處理

在C語言中,若是想要調用系統的某個函數,必須首先包含該函數聲明所在的頭文件,例如hellowrld程序中調用printf()函數聲明,就是位於系統目錄C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt下的頭文件stdio.h。
stdio.h

若是包含的文件在當前目錄下,使用#include "頭文件",若是該頭文件在系統目錄下,則使用#include <>。而編譯器查找當前目錄下的頭文件時若是未找到,還會去系統目錄下查找對應的頭文件。

#include的本質就是將包含的頭文件內容所有複製到源文件中去。
如何驗證這一點呢?

首先在項目c-core-programming-foundational的頭文件下新建篩選器Chapter1,並建立頭文件guanglei.h
guanglei.h
而後把以前源文件helloworld.c的源碼複製到guanglei.h中
guanglei.h
以後定義源文件guanglei.c
guanglei.c

該源文件的內容只須要使用#include "guanglei.h" 便可運行。
guanglei.h
可是Visual Studio 2019 解決方案(例如c-core-programming)下每一個項目(c-core-programming-foundational)只能有一個包含main方法的源程序,不然程序運行時會出錯。
定義多個main方法會出差錯
這裏將以前helloworld程序中的main方法改爲別的名字(例如helloworld_main)便可。

而後再次運行程序,運行結果和以前的helloworld程序結果同樣
#include

#include <stdio.h>表示包含頭文件stdio.h,std表示標準庫,是能夠移植的。也就是helloworld.c能夠運行在各個操做系統下。

Windows10 1903 &CLion 2019.2
Windows10 1903 &CLion 2019.2

Ubuntu18.04 & CLion 2019.2
運行以前必須先安裝CMake,使用sudo apt install cmake安裝便可
Ubuntu18.04 & CLion 2019.2

而stdio表示標準輸入輸出,printf()函數正是一個輸出函數。
stdlib表示標準庫,system()函數正是一個標準庫函數。
頭文件只存放了函數的定義,至於函數的實現,在對應的系統庫文件中。

1.10.2 main函數

main函數是C程序的入口,一個項目只能有一個main函數,不然程序運行時會提示定義多個main函數。
當程序運行時,系統自動調用main函數,程序從main函數的第一行開始執行,若是其餘函數想要獲得執行,那麼必須被main函數直接或者間接調用

int helloworld_main(int argc, char* argv[]) {
    printf("Windows10 1903 & Visual Studio 2019 Hello World \n");
    system("pause");
    return 0;
}
  • main函數左邊的int是函數的返回值,右邊()的內容表示函數的參數,外部數據經過函數的參數傳遞到函數的內部處理。

  • {}表示函數的函數體,也就是函數執行的全部內容都包含在{}中,它是成對出現的。

  • printf函數是系統自帶的函數,用於將""包含的字符串按照指定的格式輸出到終端,終端能夠是控制檯、網頁或者是文件,目前是輸出到控制檯。

  • \n表示換行,這裏就是輸出內容以後換行。

  • 分號(;)表示一條語句結束,C語言每條執行語句都須要以分號(;)結束,若是不加上分號會發生編譯錯誤。

  • system("pause")表示程序暫停,輸入任意鍵後退出,若是在Visual Studio中編寫C程序必須加上system("pause"),不然程序運行完成後就直接退出。使用CLion、QT不須要加上system("pause")。

  • return 0表示將int類型的值返回給main函數的調用方(系統)並結束main函數,return語句以後的代碼都不會再執行了,0表示正常結束。

在源文件function.c中定義了一個add方法,傳遞兩個整數參數,返回兩個整數相加的結果。而且該方法在主函數的prinf方法中被調用,用於輸出兩個整數相加的結果。
printf函數中的%d表示對應位置的參數按照整數輸出。

#include <stdlib.h>



int add(int source,int target) {
    return source + target;
    printf("不可達代碼\n");
}


int main(int argc,char* argv[]) {
    int source = 50;
    int target = 100;
    printf("%d加上%d的結果是%d\n",source,target,add(source,target));
    system("pause");
    return 0;
}

程序運行結果代表add方法的return語句以後的輸出語句printf("不可達代碼\n")並無執行,若是想要add方法獲得執行,在main方法中調用便可,調用時須要傳遞對應的參數。
程序運行結果

1.10.3 註釋

註釋是用於描述程序的功能,爲了便於程序後期的維護,在開發過程當中應該添加適量的註釋,編譯器在預編譯時會刪除註釋,因此註釋的內容不會影響程序的結果。

C語言中支持的註釋包含單行註釋(//)和多行註釋(/**/)兩種,單行註釋顧名思義就是註釋一行,多行註釋能夠註釋多行,須要注意的是多行註釋不可以嵌套使用,不然會發生編譯錯誤。

增長單行註釋和多行註釋後的helloworld

#include <stdio.h> 
#include<stdlib.h>
/* 個人第一個C程序 @author liuguanglei ittmelinedotnet@gmail.com @version 2019/08/20 */
int main(int argc, char* argv[]) {
    //快捷鍵F12能夠查看函數定義 Ctrl+ -返回
    printf("Windows10 1903 & Visual Studio 2019 Hello World \n");
    system("pause");
    return 0;
}

1.11 Windows經常使用命令

1.11.1 Windows命令概述

主流的操做系統(Windows,Linux(Ubuntu),MacOS)及大多數應用程序都提供了基於命令行和圖形化界面兩種交互方式,而移動端是採用手勢觸控、語音等進行交互。做爲普通用戶來說,圖形化界面容易上手,並且交互效果更加直觀。

可是做爲一個程序員來說,應該去熟悉各個操做系統的命令行的使用,由於命令行相對圖形化界面而言,絕大多數場景下使用更加高效。並且圖形化界面本質是對命令行的封裝,能用圖形化界面實現的基本均可以採用命令行實現。並且在服務器端(CentOS,RedHat)基本上是不會安裝圖形界面。

Windows系統可使用快捷鍵Windows+r調出運行
運行
後輸入cmd,即可以進入Windows下的命令行終端
命令行終端
Windows下經常使用的文件目錄和系統應用相關的命令以下所示,只要開啓了終端就能夠在終端內經過使用文件目錄相關和系統應用相關的命令實現快捷操做。

1.11.2 Windows經常使用命令

  • 文件目錄相關命令
命令名稱 功能描述
dir 列出當前目錄列表
cd 切換目錄(只能在根盤符(例如C盤)內切換)
md 建立目錄
del 刪除文件
type 顯示文本文件內容
cls 清除屏幕內容
exit 退出終端
  • 系統應用相關命令
命令名稱 功能描述
notepad 記事本
calc 計算器
mspaint 畫圖
explore 文件資源管理器
timedate.cpl 日期和時間
cleanmgr 磁盤清理
desk.cpl 分辨率設置
powercfg.cpl 電源設置
regedit 註冊表編輯器
msconfig 系統配置
mstsc 遠程鏈接
firewall.cpl 防火牆
appwiz.cpl 添加或修改程序
tasklist 查看進程列表
taskkill /f /im process-name.exe 關閉指定進程
msinfo 系統信息
sticky notes 便籤
ipconfig 查看ip
winver 查看windows版本
echo 顯示文本內容 例如echo %path% 查看系統環境變量
ping 檢測網絡是否暢通

1.11.3 system函數

system函數用於C程序中調用各大操做系統的命令和應用程序,被調用的命令和應用程序以字符串的方式做爲system函數的參數傳入。

實現讀取用戶輸入的命令,並執行該命令

#include <stdio.h>
#include <stdlib.h>

/* 使用system函數執行用戶輸入的命令 @author tony ittimelinedotnet@gmail.com @version 2019/08/20 */
int main(int argc,char* argv[]) {

    printf("請輸入你要執行的命令\n");
    //定義數組保存用戶輸入的指令
    char str[100] = { 0 };
    //使用scanf_s函數讀取用戶輸入的指令
    scanf_s("%s", str);
    //執行命令
    system(str);
    return 0;

}

由於system函數位於stdlib.h頭文件中,意味着它是一個能夠跨平臺使用的函數,Visual Studio 2019中可使用F12快捷鍵跳轉到函數的定義。使用Ctrl+-快捷鍵實現後退。
可是各大操做系統的命令和應用程序是不相同的,例如在Windows上使用system函數傳遞字符串參數"notepad"時能夠打開記事本,而移植到了類Unix上則沒法調用記事本。

1.12 C語言的運行流程

C語言編寫的程序通常都要通過編寫源文件->預處理->編譯->彙編->連接後運行這幾個流程。
C語言程序運行流程

  • 預處理
    預處理主要是宏替換、包含頭文件、條件編譯以及刪除註釋等操做,預編譯階段生成文件的後綴名一般是.i。
  • 編譯
    編譯主要是將預處理好的文件生成彙編文件,編譯後文件的後綴名一般是.s。
  • 彙編
    彙編主要是將彙編文件生成二進制文件,彙編後的文件的後綴名一般是.o。
  • 連接
    連接主要是將各個二進制文件、庫函數、啓動代碼生成可執行文件。

接下來編寫源程序program_running_process.c,而後結合Windows上的GCC編譯器提供的各個選項實現預處理、編譯、彙編、連接,關於GCC的安裝和配置能夠參考
Visual Studio Code實現Hello World章節的內容。

#include <stdio.h>
//定義浮點型的常量
#define PI 3.14
/* C語言程序的運行流程 @author tony ittimelinedotnet@gmail.com @version 2019/08/20 */
int main(int argc, char* argv[]) {

    printf("PI =%lf\n", PI);
    return 0;
}

預處理使用 gcc -E 選項便可實現,其中-o表示輸出文件的名稱

D:\workspace\c\visualstuido2019\c-core-programming\c-core-programming-foundational\c-core-programming-foundational>gcc -E  program_runing_process.c -o program_runing_process.i

預處理完成之後,生成的文件program_running_process.i的大小是54kb
預處理
當預處理完成之後,定義的常量被替換成實際的值,而#include包含的頭文件內容也被複制到預處理的生成的文件中
預處理

編譯經過gcc -S 選項實現

D:\workspace\c\visualstuido2019\c-core-programming\c-core-programming-foundational\c-core-programming-foundational>gcc -S program_runing_process.i -o program_runing_process.s

編譯會生成彙編文件

 .file	"program_runing_process.c"
 .text
 .def	__main; .scl 2; .type 32; .endef
 .section .rdata,"dr"
.LC1:
 .ascii "PI =%lf\12\0"
 .text
 .globl	main
 .def	main; .scl 2; .type 32; .endef
 .seh_proc	main
main:
    pushq	%rbp
 .seh_pushreg	%rbp
    movq	%rsp, %rbp
 .seh_setframe	%rbp, 0
    subq	$32, %rsp
 .seh_stackalloc	32
 .seh_endprologue
    movl	%ecx, 16(%rbp)
    movq	%rdx, 24(%rbp)
    call	__main
    movq	.LC0(%rip), %rax
    movq	%rax, %rdx
    movq	%rdx, %xmm1
    movq	%rax, %rdx
    leaq	.LC1(%rip), %rcx
    call	printf
    movl	$0, %eax
    addq	$32, %rsp
    popq	%rbp
    ret
 .seh_endproc
 .section .rdata,"dr"
 .align 8
.LC0:
 .long	1374389535
 .long	1074339512
 .ident	"GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0"
 .def	printf; .scl 2; .type 32; .endef

彙編經過gcc -c 選項實現

D:\workspace\c\visualstuido2019\c-core-programming\c-core-programming-foundational\c-core-programming-foundational>gcc -c program_runing_process.s -o program_runing_process.o

連接gcc沒有提供選項,這裏只要執行gcc program_running_process.o -o program_running_process.exe就會連接生成可執行文件

D:\workspace\c\visualstuido2019\c-core-programming\c-core-programming-foundational\c-core-programming-foundational>gcc program_runing_process.o -o program_runing_process.exe

windows下的可執行文件後綴名默認是.exe,固然gcc編譯器不關心後綴名,若是你的ubuntu或者macOS下安裝了gcc,也能夠將C程序編譯生成.exe後綴的可執行文件。

在Linux下若是想要查看你的C序(編譯生成的可執行文件引用了哪些系統庫,可使用ldd命令查看

 

ldd查看程序依賴的系統庫
ldd查看程序依賴的系統庫

 

guanglei@ubuntu:~/CLionProjects/c-core-programming$ cd cmake-build-debug/
guanglei@ubuntu:~/CLionProjects/c-core-programming/cmake-build-debug$ ls
c_core_programming  c_core_programming.cbp  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
guanglei@ubuntu:~/CLionProjects/c-core-programming/cmake-build-debug$ ldd c_core_programming
        linux-vdso.so.1 (0x00007ffdc1fcf000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0011a14000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0012007000)

1.13 Visual Studio 2019調試程序

在後期編寫程序時,經驗不足的開發人員一般會遇到兩種錯誤:編譯錯誤和運行時錯誤,編譯錯誤一般是編寫的程序不知足編譯器的語法規範,而運行時錯誤則是程序運行時發生的錯誤,想要排查程序運行時的錯誤,就須要使用IDE提供的調試功能。

在源文件debug.c中定義一個返回兩個整數相乘的方法mul,而後在main函數中定義兩個變量,並調用兩個整數相乘的方法,輸出計算結果

#include <stdio.h>
#include <stdlib.h>


/* 定義兩個整數相乘並返回 */
int mul(int source,int target) {

    return source * target;
}
/* 調試程序 @author liuguanglei ittimelinedotnet@gmail.com @version 2019/08/21 */
int main(int argc, char* argv[]) {

    //定義兩個變量
    int source = 12;
    int target = 12;
    printf("source = %d \t target = %d \n", source,target);

    //調用兩個整數相乘的方法,並將計算的結果保存到整數變量result中
    int result = mul(source,target);
    //輸出兩個整數相乘的結果
    printf("result = %d \n",result);
    system("pause");
    return 0;
}

在調試程序前首先須要下斷點,可使用快捷鍵F9下斷點或者取消斷點
下斷點
而後使用F5調試運行程序,程序會在以前下過斷點的地方暫停,此時能夠在Visual Studio提供的窗口中觀察變量的值
觀察變量
若是想要一行一行調試代碼,可使用快捷鍵F11,當遇到函數時(例如這裏的mul函數),會進入函數的內部一行一行執行,直到該函數結束爲止。

若是調試時不想進入函數的內部,可使用快捷鍵F10,當程序中調用了其餘函數時不會進入其餘函數內部,可是函數會被調用。

若是調試時想要從一個斷點跳到另一個斷點,可使用shift+F11實現。

若是想要查看函數調用的定義,可使用快捷鍵F12,退出查看函數定義則使用Ctrl+ -。
在調試代碼的過程當中,還可能會註釋部分錯誤的代碼,註釋可使用快捷鍵Ctrl+k,u實現,而取消註釋可使用Ctrl+k,u實現。

若是源文件中的代碼格式比較凌亂,可使用Ctrl+k,f快速格式化代碼。

1.14 Visual Stuido 2019技巧錦集

1.14.1 Visual Studio 2019解決4096錯誤

Visual Studio 但願用戶使用Visual Studio提供的非標準庫函數,可是程序員但願使用標準庫函數,由於標準庫是能夠移植的。
若是在Visual Studio中使用標準的庫函數,就會引起4996錯誤相似於這種提示:error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.這裏的strcpy是標準的庫函數,而在Visual Studio中使用這個函數引起了4996錯誤。

#define _CRT_SECURE_NO_WARNINGS //防止4996錯誤
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* vs4996錯誤 error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. @author liuguanglei ittimelinedotnet@gmail.com @version 2019/08/21 */
int main(int argc,char *argv[]) {
    //定義一個字符串
    char buf[32] = "";
    //使用strcpy實現將字符串hi string複製到變量buf中
    strcpy(buf, "hi string");
    //輸出字符串的內容
    printf("buf = %s \n",buf);
    system("pause");
    return 0;

}

如何解決Visual Studio中的4996錯誤呢?

方案1:在源文件(例如這裏的vs4996.c)的第一行定義宏

#define _CRT_SECURE_NO_WARNINGS //防止4996錯誤

方案2:在源文件(例如這裏的vs4996.c)的第一行定義以下內容:

#pragma warning(disable:4996)

1.14.2 Visual Studio 2019配置代碼片斷

在後期編寫C程序中,須要反覆使用到以下的代碼片斷

//#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>
/* @author liuguanglei ittimelinedotnet@gmail.com @version */
int main(int argc,char *argv[]) {

    
}

這裏爲了減輕工做量,使用Visual Studio 2019提供的代碼片斷管理器來實現經過輸入配置的快捷鍵生成模板代碼。

首先自定義代碼片斷文件MyCCode.snippet

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>MyCCodeTemplate</Title>
            <Shortcut>mcct</Shortcut>
            <Description>c的標準模板代碼</Description>
            <Author>Microsoft Corporation</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
                <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Code Language="cpp">
            <![CDATA[#define _CRT_SECURE_NO_WARNINGS
            #include <stdio.h>
            #include <stdlib.h>
      /*
        
          @author liuguanglei ittimelinedotnet@gmail.com
          @version 
      */
            int main(int argc, char *argv[])
            {
                system("pause");
                return 0;
            }]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

而後進入Visual Studio 2019 菜單 工具->代碼片斷管理器
代碼片斷管理器
選擇代碼片斷管理器的語言爲C++,而後選中My Code Snippets
導入自定義代碼管理器
把MyCCodeTemplate.snippet導入進來
MyCCode.snippet
代碼片斷設置位置
MyCCode.snippet

導入成功以後新建源文件,在源文件中輸入快捷鍵mcct就能夠生成以下的代碼片斷

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/* @author liuguanglei ittimelinedotnet@gmail.com @version */
int main(int argc, char* argv[]) {
    system("pause");
    return 0;
}

想要了解代碼片斷的更多內容,請移步官網

相關文章
相關標籤/搜索