只要您的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