c语言学习笔记十四
多目標文件的鏈接
示例代碼如下:
test18.c
char stack[512];
int top=-1;
void push(char c){
stack[++top]=c;
}
char pop(){
return stack[top--];
}
int is_empty(void){
return top==-1;
}
?
test19.c
#include <stdio.h>
int a,b=1;
int main(void){
?push('a');
push('b');
push('c');
? ? ? ?while(!is_empty()){
putchar(pop());
}
putchar("\n");
return 0;
}
一起編譯: gcc test19.c test18.c -o test19
分開編譯: gcc -c test19.c
? ? ? ? ? ?gcc -c test18.c
? ? ? ? ? ?gcc test19.o test18.o -o test19
運行程序:./test19
查看符號表:readlf -a test19
以下是合并后的符號表信息?
? [13] .text ? ? ? PROGBITS ? 08048330 000330 00021c 00 ?AX ?0 ? 0 16
? ? ? 52: 08048481 ? ?19 FUNC ? ?GLOBAL DEFAULT ? 13 is_empty
? ? ? 54: 08048466 ? ?27 FUNC ? ?GLOBAL DEFAULT ? 13 pop
? ? ? 68: 080483e4 ? ?88 FUNC ? ?GLOBAL DEFAULT ? 13 main
? ? ? 69: 0804843c ? ?42 FUNC ? ?GLOBAL DEFAULT ? 13 push
? [24] .data ? ? ? PROGBITS ? 0804a00c 00100c 000010 00 ?WA ?0 ? 0 ?4
? ? ? 49: 0804a014 ? ? 4 OBJECT ?GLOBAL DEFAULT ? 24 b
? ? ? 59: 0804a018 ? ? 4 OBJECT ?GLOBAL DEFAULT ? 24 top
? [25] .bss ? ? ? ?NOBITS ? ? 0804a020 00101c 000220 00 ?WA ?0 ? 0 32
? ? ? 66: 0804a028 ? ? 4 OBJECT ?GLOBAL DEFAULT ? 25 a
? ? ? 71: 0804a040 ? 512 OBJECT ?GLOBAL DEFAULT ? 25 stack
查看默認鏈接角本:ld --verbose
?
?示例代碼如下:
? ?ENTRY(_start) //整個程序的入口點,可以修改為其他函數
? ?PROVIDE (__executable_start = SEGMENT_START("text-segment",?
0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) +?
SIZEOF_HEADERS; ? //text Segment的起始地址, 每個段的格式,段名:{組成}
定義和聲名
?示例代碼:
test19.c
#include <stdio.h>
int a,b=1;
int main(void){
?push('a');
push('b');
push('c');
? ? ? ?while(!is_empty()){
putchar(pop());
}
putchar("\n");
return 0;
}
以上函數用以下命令編譯會出問題
? gcc -c test19.c -wall
? 錯誤信息: ?
?test19.c: 在函數‘main’中:
?test19.c:4: 警告: 隱式聲明函數‘push’
?test19.c:8: 警告: 隱式聲明函數‘is_empty’
?test19.c:9: 警告: 隱式聲明函數‘pop’
?
??
?函數聲明沒有明確指出參數類型和個數,不算函數原型,所以編譯器只能用作隱式聲
明
正確方法:
?#include <stdio.h>
/*聲明用到的幾個函數的原型?
?*Extern 關鍵字表示這個標識符具有External Linkage.
?* 外部鏈接:external linkage 多個文件中聲明多次也都代表同一標識符
?* static 作函數聲明,
?* 內部鏈接:internal linkage (某個文件)中聲明多次也都代表同一標識符
?*/
extern void push(char);
extern char pop(void);
extern int is_empty(void);
/*
?*如果相直接訪問test18.c上的top屬性
?*有點像java中的子類的味道extends?
?*它的存儲空間是在test18.c中分配
?* extern在作函數聲明時可寫不可寫都行
?* 但在變量聲明時必需要寫
?*/
extern int top;?
int a,b=1;
int main(void){
?push('a');
push('b');
push('c');
? ? ? ?while(!is_empty()){
putchar(pop());
}
putchar('\n');
return 0;
}
示例代碼:
test18.c
char stack[512];
/*?
?*如果不想讓外界訪問可以用static來修飾
?*有點像java 中的private修飾符
?*/
int top=-1;
void push(char c){
stack[++top]=c;
}
char pop(){
return stack[top--];
}
int is_empty(void){
return top==-1;
}
頭文件
?為了避免重復的代碼(即在test.19中用作函數聲明的代碼)
? 可以將其抽象到一個頭文件中(有點java的味道)
?
示例代碼如下:
test18.h頭文件
/*
?* 此處定義的STACK_H這個宏是為了防止頭文件被得復包含
?*/
#ifndef STACK_H
#define STACK_H
extern void push(char);
extern char pop(void);
extern int is_empty(void);
#endihile(!iq
test19.c文件修改為:
#include <stdio.h>
/*
?* <頭文件> 直接從庫文件中查找
?* "頭文件" 先從當前目錄查找,然后到庫目錄中查詢
?* 這跟c++中有點類似
?* 如果頭文件放在子錄中s
?* 可以用如下格式: #include "子目錄名/test18.h"
?*/
#include "test18.h"
?
int a,b=1;
int main(void){
?push('a');
push('b');
push('c');
? ? ? ?while(!is_empty()){
putchar(pop());
}
putchar('\n');
return 0;
}
注:如果頭文件放到下一子目錄中,需要用-I 參數指定目錄名
? ? ?命令格如下
? ? ?gcc -c test19.c -I ?子目錄名
? ??
轉載于:https://www.cnblogs.com/retacn-yue/archive/2012/09/20/2761233.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: 2012开博
- 下一篇: JME3中级手册一API特征映射1