001 c++ 如何作業
-
任何以 # 開頭的陳述句,都是預處理陳述句,所謂的預處理陳述句,在編譯之前,就已經被處理了
-
關鍵字 include:找到 <> 檔案(通常稱為“頭檔案”),然后將 <> 中的所有內容拷貝到現在的檔案里
-
main()比較特殊,雖然它的回傳值型別是 int,但它不一定需要回傳值,如果不設定回傳值,默認回傳 0
-
<< 運算子叫做多載運算子,可以看成是一個函式(多載運算子 == 函式)
-
解決方案平臺(Solution Platforms):編譯代碼的目標平臺;
x86:目標平臺是 windows32 位(生成 32 位的 windows 應用程式) -
預處理后,我們的檔案將被編譯,編譯器將所有 c++ 代碼 -> 二進制的機器碼
-
源檔案.cpp --編譯--> 目標檔案.obj --鏈接--> 可執行檔案.exe
-
鏈接:將 .obj 檔案鏈接(合并)到一起,編成一個可執行檔案,比如函式宣告,是不同.cpp之間的合并,這里強調一下,只有函式呼叫的時候,才會產生鏈接,宣告的時候,是不會進行鏈接的,宣告只是在函式被呼叫的時候,能夠找到合適的鏈接函式
-
頭檔案不會被編譯,頭檔案拷貝過來時,已經被編譯過了;
編譯一個單獨的檔案時,不會 link,單個檔案編譯快捷鍵:ctrl + F7
Main.cpp
#include <iostream> # 這一條陳述句其實包含了 50623 行代碼,所以 Main.cpp 檔案才會很大
void Log(const char* message);
int main()
{
// std::cout << "Hello World!" << std::endl; // 將字串 Hello World! 推送到 cout 流中,然后列印到終端;endl 告訴終端,跳到下一行
Log("Hello World!!");
std::cin.get(); // 程式暫停執行,直到按下 enter 鍵
}
Log.cpp
#include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
002 c++ 編譯器如何作業
-
編譯器本質作業:將我們的文本檔案 -> 目標檔案,便于后續的鏈接
-
我們先按照編程語言的規則,將代碼進行記號化和決議成編譯能理解和推理的格式,然后編譯器對所有的代碼進行預處理,這兒會產生抽象語法樹,編譯器的作業就是將我們的代碼轉換成常量資料或指令,一旦編譯器生成這個 AST ,它可以生成實際的機器碼
-
抽象語法樹(abstract syntax code,AST)是源代碼的抽象語法結構的樹狀表示,樹上的每個節點都表示源代碼中的一種結構,這所以說是抽象的,是因為抽象語法樹并不會表示出真實語法出現的每一個細節,比如,嵌套括號被隱含在樹的結構中,并沒有以節點的形式呈現
-
編譯器只會編譯 .cpp 的 c++ 檔案,這些 cpp 檔案被稱為翻譯單元(一個 CPP 檔案不一定等于一個翻譯單元,如果專案較小,那么每個 CPP 檔案都是一個翻譯單元)
-
實際上,沒有所謂的檔案,編譯器根本不 care 檔案不檔案,檔案只是提供給編譯器源代碼的一種方式而已
-
下面的例子,主要想說明的就是,編譯器在處理頭檔案時,會把頭檔案中的所有內容都復制到當前檔案
-
強調一下,我們平時在寫代碼的時候,要盡可能的簡潔,盡可能的優化我們的代碼,比如將 Math.cpp 中的 int result = a * b; 一行去掉,直接 return a * b; 編譯在作業時,會節省四行代碼
Math.cpp
int Math(int a, int b)
{
int result = a * b;
return result;
#include "EndBrace.h"
EndBrace.h
}
003 c++ 聯結器如何作業
-
鏈接的主要作業:找到每個符合和函式在哪,并把他們鏈接起來
-
源檔案被編譯之后,每個檔案都是單獨的翻譯單元,他們之間沒有任何關系,不能互動
-
下面的例子很好的說明了鏈接的作用,Multiply() 定義了,即使你在當前的翻譯單元里沒有呼叫 Multiply(),但是聯結器會認為你在其他的檔案里會用到這個函式,所以,它還是會被進行鏈接,函式內部的函式呼叫,也會進行鏈接,所以呼叫的 Log() 和 Log.cpp 檔案中的 Logr() 不對應,就會產生鏈接錯誤
-
我們可以使用 static 函式,直接規定死,Multiply() 只在當前檔案下使用,不讓它和其他變數或函式進行鏈接,就會避免上述錯誤
Math.cpp
# include <iostream>
void Log(const char* message);
// static int Multiply(int a, int b)
int Multiply(int a, int b)
{
Log("Multiply");
return a * b;
}
int main()
{
std::cin.get();
}
Log.cpp
#include <iostream>
void Logr(const char* message)
{
std::cout << message << std::endl;
}
-
下面介紹一下,函式定義重復,導致的鏈接錯誤
-
這里其實會報錯的,Math.cpp 和 Log.cpp 都包含了頭檔案 # include "Log.h",也就是說,Log() 的定義被復制了兩遍,產生重復鏈接錯誤,如果我們將 Log() 的修飾符改為 static 或 inline ,則會消除鏈接錯誤
-
還有一種解決辦法就是,在 Log.h 中只宣告 Log(),然后在 Log.cpp 中定義 Log(),這樣也不會產生鏈接錯誤
Log.h
# include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
Log.cpp
# include "Log.h"
void InitLog()
{
Log("Initialized Log");
}
Math.cpp
# include <iostream>
# include "Log.h"
static int Multiply(int a, int b)
{
Log("Multiply");
return a * b;
}
int main()
{
std::cout << Multiply(5, 8) << std::endl;
std::cin.get();
}
- inline 的作用就是獲取實際的函式體,并將函式呼叫替換為函式體,比如在 Log.cpp
# include "Log.h"
void InitLog()
{
// Log("Initialized Log");
std::cout << "Initialized Log" << std::endl;
}
004 變數和函式
-
當我們創建一個變數的時候,他們會被放到記憶體(堆和堆疊)里
-
不同變數型別之間的唯一區別:在記憶體中所占大小,而不同型別的變數所占記憶體大小與編譯器有關
-
int 資料型別可以存盤 -20億 ~ +20 億之間(約數)的值
-
變數的型別大小與它能存盤多大的數字直接相關
-
unsigned 資料型別取值范圍 0 ~ 40 億,是因為它把符號位移除了
# include <iostream>
int main()
{
float variable = 4.4f; // 在值的后面添加 f 區分 float 和 double
double var = 9.9;
std::cout << variable << std::endl;
std::cout << var << std::endl;
std::cin.get();
}
-
bool 資料型別的取值為 true 或 false,其在計算機中表示為 1 或 0,但是該型別的變數在記憶體中,占 1Byte ,雖然其只是 0 或 1,只用 1bit 就行,但是在處理尋址記憶體時,不能尋址只有 1bit 位的內容,只能尋址位元組
-
可以使用 sizeof() 查看變數所占記憶體
Main.cpp
# include <iostream>
int main()
{
bool var = false;
std::cout << sizeof(var) << std::endl; // 1
std::cin.get();
}
-
函式,不是 c++ 類里的
-
main() 是一個特殊的函式,可以不寫函式函式回傳值,但是其他的所有函式,都需要寫回傳值,否則會報錯
-
函式宣告通常存盤在頭檔案中,在翻譯單元或 cpp 檔案實作定義
004 c++ 頭檔案
-
對于 c++ 而言,頭檔案通常用于宣告某些型別的函式
-
函式完美地解決了重復代碼的問題,而頭檔案完美解決了函式呼叫必須有宣告的問題,有了頭檔案,就不用在每個翻譯單元宣告函式了
-
如果我們在 .h 頭檔案里包含了 #include
那么在翻譯單元里,只要包含了 .h 檔案,不添加 #include 也可以 -
pragma 是一個被發送到編譯器或前處理器的預處理指令
-
pragma once 監督頭檔案,阻止單個頭檔案多次被包含
Log.h
# pragma once // 只包括這個頭檔案一次
-
如果我們要包含的檔案,在其中的一個檔案夾里,用尖括號 <> 告訴編譯器,搜索包含路徑檔案夾,說白了就是,用引號可以指定相對路徑
-
而引號 "" 通常是告訴編譯器,包含相對于當前檔案的檔案
-
c++ 標準庫,通常沒有后綴 .h,是為了和 c 進行區分
-
在 vs 里,可以右鍵打開檔案,查看所選頭檔案完整內容;右鍵函式名,可以查看函式定義
持續更新ing....
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/552176.html
標籤:C++
上一篇:在 IDEA 中創建 Spring Boot 專案的方式(詳細步驟教程)
下一篇:返回列表