嵌入式linux學習筆記:07_C語言_終

一、 Linux GCC編譯器編譯過程

1、一步到位:編譯命令: gcc *** .c -o ***

                 GCC編譯器
  高級語言     --------------->   二進制文件
   ***.c                            ***

2、細分每個編譯過程,可以分爲4個步驟

 高級語言       預處理              編譯           彙編            鏈接      二進制文件

   ***.c        ------>     ***.i   ----->  ***.s   ----->  ***.o   ------>      ***

1)這些步驟如何處理?
其實這些步驟都是gcc編譯器的參數來的,我們只需要查詢ubuntu即可,–> man 1 gcc
-E Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output. //在預處理階段之後就停止了,輸出的文件***.i還是C語言文件。

-S Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified. //在編譯階段之後就停止,不進行彙編,輸出的文件***.s是彙編文件。

-c Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file. //在彙編階段之後就停止了,但是不進行鏈接,輸出的文件***.o是二進制文件。

2)舉實例。

準備高級C語言: hello.c

預處理: 把程序中頭文件、條件編譯、宏定義處理。

  gcc hello.c -o hello.i -E       hello.i: C語言文件

編譯:檢查程序中語法是否正確

gcc hello.i -o hello.s -S         hello.s: 彙編文件

彙編: 將程序地址重新排列

   gcc hello.s -o hello.o -c        hello.o: 二進制文件

鏈接: 鏈接某些特定的庫文件(標準C庫、線程庫…)

   gcc hello.o -o hello             hello:  二進制文件(可執行)  

二、自定義頭文件

1、自定義頭文件中可以寫什麼內容?
包含系統的頭文件:#include <stdio.h>
進一步系列函數聲明:int fun (int x, int y);
宏定義:#define
結構體聲明:

struct mydata{
	xxx;
	yyy;
}

2、自定義頭文件格式
1)文件後綴:****.h
2) 將.c文件中系統的頭文件、函數聲明、宏定義、結構體聲明等全部寫入頭文件head.h

#ifndef _HEAD_H_   --> 如果沒有定義_HEAD_H_
#define _HEAD_H_  --> 那麼就定義_HEAD_H_
/* 系統頭文件 */
#include <stdio.h>
/* 結構體聲明 */
struct mydata{
       int a;
       char b;
};
/* 函數聲明 */
int fun(int x,int y);
/* 宏定義 */
#endif   -> 結束定義

三、宏定義

1、宏定義是什麼? -> 就是一個簡單的替換
其實宏定義與枚舉類型非常相似,都是可以使用某些常量變得有意義,宏定義除了可以替換int類型,還可以是字符/字符串…
2、宏定義處理的時間?
發生在編譯的預處理階段,而不是在運行時間。
3、宏定義如何寫?
1)無參宏
#define OK 0 -> OK 等價於 0
#define ERROR -1
#define MUSIC “xxx.mp3”
實例:

#include <stdio.h>
#define OK 0
int main()
{
	int a = 0;
	if(a == OK)
		printf("helloworld\n");
	return 0;
}
預處理階段之後:
stdio.h已經展開
int main()
{
	int a = 0;
	if( a == 0)
		printf("helloworld\n");
	return 0;
}

2)帶參宏
#define XYZ(a,b) ab
int ret = XYZ(10,20);
ret = 10
20 =200;
int ret = XYZ(10+10,20);
ret = 10+10*20 = 210;

4、注意的事項
1)宏定義只是發生了預處理階段,佔用預處理時間,不佔用運行時間。
2)宏定義既可以使用大寫字母組成,也可以使用小寫字母組成。

四、條件編譯?

1、什麼是條件編譯?
根據條件的真假來編譯代碼,與註釋類似的!

#if 1   -> 代表在endif之前的代碼都需要編譯!
       printf("appletree!\n");
#endif

2、實例

#include <stdio.h>
int main()
{
	#if 1
		printf("appletree!\n");//大家好纔是真的好
	#endif

	#if 0
		printf("helloworld!\n");
	#endif
}
以下那內容會在預處理階段全部刪除!
#if 0
	printf("helloworld!\n");
#endif
//大家好纔是真的好

五、關於預處理階段細節問題

1、由於頭文件中有函數聲明,所以頭文件必須在函數調用之前必須聲明。
2、宏定義#define 頭文件#include 條件編譯#if 都是以#開頭。
3、如果在同一行出現多個預處理語句,只會執行第一個預處理語句。
警告:warning: extra tokens at end of #include directive

六、多個.c文件的拆分

實例:
1、頭文件:包含系統頭文件、宏定義、函數聲明、結構體聲明

#ifndef _HEAD_H_
#define _HEAD_H_
#include <stdio.h>
typedef struct mydata{
	int a;
	int b;
}mydata;
int fun(int x);
#endif

2、包含main函數在內的.c -> 一般main.c裏面只有main函數

#include "head.h"
int main(int argc, char *argv[])
{
	int a = 100;
	mydata A;
	A.a = 10;
	A.B = 20;
	int x = fun(a);
	if(x == OK)
		printf("helloworld!\n");
	my_fun(A);
#if 1
	printf("appletree!\n");
#endif
	return 0;
}

3、功能函數1

#include "head.h" -->每一個功能函數都需要包含頭文件,因爲功能函數也是用printf()函數!
int fun(int x)
{
	printf("x = %d\n",x)
	return x;
}

4、功能函數2

#include <stdio.h>
int my_fun(mydata B) //B = A
{
	printf("B.a = %d\n",B.a);
	printf("B.b = %d\n",B.b);
	retrun 0;
}

ok
C語言複習到此告一段落先

下一階段 --> 進入linux 基礎

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