C/C++查閱引用(include)或使用巨集(macro)後編譯有問題的程式碼

為什麼需要查閱 C/C++引用(include)或使用巨集(macro)編譯出錯的程式碼,因為使用巨集編譯時發生的錯誤訊息提示的程式碼行數,往往不是原始碼(source code)中看到的行數。

在學習與除錯的時候總覺麻煩,下面就展示該如何查閱引用/使用巨集後的程式碼。


2008年曾寫過相關的紀錄文,這裡舊事重提並搭配圖文說明。

首先了解一下為什麼會有這件事情,這要先簡要了解gcc test.c之後編譯器所作的事情。以下引用自wiki條目:編譯器

現代編譯器的主要工作流程如下: 原始碼(source code)→ 預處理器(preprocessor)→ 編譯器(compiler)→ 組譯程式(assembler)→ 目的碼(object code)→ 連結器(linker)→ 執行檔(executables)

因此在進入到編譯器之前,還有個preprocessor流程,也就是這裡導致了程式碼行數,所以我們可以要求gcc輸出這個階段的程式碼給我們看。使用的指令如下:

gcc -E test.c

在gcc的參數上加入-E就是要求輸出preprocessor的結果,這會直接顯示在console上,所以一般還會搭配管線導出。這裡小心別把程式碼本身test.c給蓋掉了,所以我們加個前綴給它pp_test.c

gcc -E test.c > pp_test.c

前處理之後所得到的還是c程式碼,所以我們命名稱,只是把系統include和macro都展開在程式碼裡頭。另外,也可以用cpp test.c > pp_test.c產生相同的輸出。

打開這個檔案你會發現有非常多#+號碼+字串的文字,這就是指它展開的位置和對應的檔案名稱,以下說明:

第1行# 0 "test.c" 是說明目前是test.c的第0行
第2行# 0 "<built-in>"是說明以下部份是內建的機制東西
第3行# 0 "<command-line>" 是說明這是由指令所提供
第4行# 1 "/usr/include/stdc-predef.h" 就是指引入的內容, 這個打開檔案都是定義macro變數沒有實際程式碼,所以就沒有內容
第5行# 0 "<command-line>" 2 就指結束這部份


第6行# 1 "test.c" 是說明目前是test.c的第1行
第7行# 1 "/usr/include/stdio.h" 1 3 4 由於test.c第一行引用了stdio.h,所以preprocessor就開始引用它的第一行
第8行# 27 "/usr/include/stdio.h" 3 4 表示跳到stdio.h的27行

第9行# 1 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 1 3 4 在stdio.h引用了libc-header-start.h
第10行# 33 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 3 4 表示跳到libc-header-start.h的33行,因為程式碼引用了features.h



留言