程序是怎麼從代碼到二進制的?——預編譯

概覽

從hello world說起。

#include <stdio.h>
int main()
{
	printf("Hello world\n"):
	return 0;
}

在這裏插入圖片描述

預編譯過程測試

在這裏插入圖片描述
vim hello.i , 如下:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

編譯過程到底發生了什麼?

·將所有的#define刪除,並且展開所有的宏定義

·處理所有的條件預編譯指令,比如#if #ifdef #elif #else #endif等

·處理#include預編譯指令,將被包含的文件插入到該預編譯指令的位置。

·刪除所有註釋“//”和”/* */”.

·添加行號和文件標識,以便編譯時產生調試用的行號及編譯錯誤警告行號。

·保留所有的#pragma編譯器指令,因爲編譯器需要使用它們

經過預編譯後的.i文件不含任何宏定義,所有的宏已經被展開並且插入到.i文件中。

添加行號和文件標識具體的含義是什麼?

比如:

# 1 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 1 3 4
# 26 "/usr/include/x86_64-linux-gnu/bits/sys_errlist.h" 3 4
extern int sys_nerr;
extern const char *const sys_errlist[];
# 782 "/usr/include/stdio.h" 2 3 4

第一個6 表示下面的內容是由某個文件的第幾行產生的。
但是最後面的幾個數字(1,2,3,4)是什麼意思?看不出來是什麼。

結果引自:http://tigcc.ticalc.org/doc/cpp.html

These are called linemarkers. They are inserted as needed into the output (but never within a string or character constant). They mean that the following line originated in file filename at line linenum. filename will never contain any non-printing characters; they are replaced with octal escape sequences.

After the file name comes zero or more flags, which are 1, 2, 3, or 4. If there are multiple flags, spaces separate them. Here is what the flags mean:

1 This indicates the start of a new file.
2 This indicates returning to a file (after having included another file).
3 This indicates that the following text comes from a system header file, so certain warnings should be suppressed.
4 This indicates that the following text should be treated as being wrapped in an implicit extern “C” block.

建議

以上即爲預編譯過程發生的事情。當不知道懷疑宏定義錯誤或者頭文件包含不對時,可以生成預編譯的.i文件來調試定位問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章