只要您的libc和鏈接器設置支持它,這應該會「自動」發生。你還沒有告訴你的平臺是什麼,所以here is one where it does work。
所以,讓我們使用snprintf創建一個愚蠢的例子。
/*
* main.c
*/
#include <stdio.h>
int main(int argc, char **argv) {
char l[100];
snprintf(l, 100, "%s %d\n", argv[0], argc);
return 0;
}
嘗試編譯並將其鏈接
$ CC=/opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-gcc
$ CFLAGS="-mcpu=arm926ej-s -Wall -Wextra -O6"
$ LDFLAGS="-nostartfiles -L. -Wl,--gc-sections,-emain"
$ $CC $CFLAGS -c main.c -o main.o
$ $CC $LDFLAGS main.o -o example
/opt/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
collect2: error: ld returned 1 exit status
它需要_sbrk
因爲newlib *printf
函數使用malloc
這需要一種方式來分配系統內存。讓我們提供一個虛擬的。
/*
* sbrk.c
*/
#include <stdint.h>
#include <unistd.h>
void *_sbrk(intptr_t increment) {
return 0;
}
並編譯
$ $CC $CFLAGS -c sbrk.c -o sbrk.o
$ $CC $LDFLAGS -Wl,-Map,"sbrk.map" main.o sbrk.o -o with-sbrk
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk
text data bss dec hex filename
28956 2164 56 31176 79c8 with-sbrk
嗯,這就是你想擺脫printf
和朋友的原因,不是嗎?現在,隨着我們的函數替換snprintf
/*
* replace.c
*/
#include <stdio.h>
#include <string.h>
int snprintf(char *str, size_t size, const char *format, ...) {
return strlen(format);
}
然後編譯
$ $CC $CFLAGS -c replace.c -o replace.o
$ $CC $LDFLAGS -Wl,-Map,"replace.map" main.o replace.o -o with-replace
$ /opt/gcc-arm-none-eabi-4_7-2013q3/bin/arm-none-eabi-size with-sbrk
text data bss dec hex filename
180 0 0 180 b4 with-replace
請注意,我們沒有使用_sbrk
存根都沒有。只要你不提供_sbrk
,你可以確定malloc
不是(不能)被鏈接和使用。
[相關問題](http://stackoverflow.com/questions/29391965/what-is-partial-linking-in-gnu-linker)和[另一個相關的問題](http://stackoverflow.com/questions/270984/g-partial-linking-instead-of-archives) – Kenney
[如何替換C標準庫函數?](http://stackoverflow.com/questions/9107259/how-to-replace-c-標準庫函數) –
我不認爲這是重複的,因爲我的問題是「我可以告訴鏈接器只使用庫中的一部分符號」,而不是「我可以替換這個特定的函數嗎?「主要區別在於,在我的問題中,如果使用的符號未從庫中明確命名,鏈接器應該解決錯誤 – FazJaxton