我正在创建一个跨系统的应用程序。例如,它使用函数textLines
,它在某些系统上实现,但不是全部。如果我只是提供自己的itoa
实现:
itoa
我知道我可以检查宏是否是预定义的,如果没有,则定义它们:
header.h:115:13: error: conflicting types for 'itoa'
extern void itoa(int, char[]);
In file included from header.h:2:0,
from file.c:2:0,
c:\path\to\mingw\include\stdlib.h:631:40: note: previous declaration of 'itoa' was here
_CRTIMP __cdecl __MINGW_NOTHROW char* itoa (int, char*, int);
有没有办法检查C函数是否已预先实现,如果没有,请实现它?或者只是简单地实现一个函数?
答案 0 :(得分:6)
鉴于您已经编写了自己的&
实现,我建议您重命名并在任何地方使用它。至少你确定你会在所有平台上获得相同的行为,并避免链接问题。
不要忘记在您的代码的评论中解释您的选择......
答案 1 :(得分:4)
我假设你正在使用GCC,因为我可以在你的路径中看到MinGW ...... GNU链接器可以通过哪种方式为你处理这个问题。所以你不知道是否有itoa
实施。试试这个:
创建一个名为my_itoa.c
的新文件(没有任何标题):
char *itoa (int, char *, int);
char *my_itoa (int a, char *b, int c)
{
return itoa(a, b, c);
}
现在创建另一个文件impl_itoa.c
。在这里,编写itoa
的实现,但添加一个弱别名:
char* __attribute__ ((weak)) itoa(int a, char *b, int c)
{
// implementation here
}
编译所有文件,最后加impl_itoa.c
。
这样,如果标准库中没有itoa
,则会链接此标准库。你可以自信地编译它是否可用。
答案 2 :(得分:2)
Ajay Brahmakshatriya's suggestion是一个很好的,但不幸的是MinGW在我检查后不支持弱定义(例如,参见https://groups.google.com/forum/#!topic/mingwusers/44B4QMPo8lQ)。
但是,我认为弱引用在MinGW中起作用。拿这个最小的例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
__attribute__ ((weak)) char* itoa (int, char*, int);
char* my_itoa (int a, char* b, int c)
{
if(itoa != NULL) {
return itoa(a, b, c);
} else {
// toy implementation for demo purposes
// replace with your own implementation
strcpy(b, "no itoa");
return b;
}
}
int main()
{
char *str = malloc((sizeof(int)*3+1));
my_itoa(10, str, 10);
printf("str: %s\n", str);
return 0;
}
如果系统提供itoa
实现,则应使用该输出,输出将为
str:10
否则,你会得到
str:no itoa
答案 3 :(得分:0)
这里有两个非常重要的相关要点:“不要这样做”这一行:
atoi
,因为it's not safe。atoi
因为它不是标准功能,并且有很好的标准功能(例如snprintf
)可以做你想要的。但是,把所有这些放在一边,我想向你介绍autoconf, part of the GNU build system。 autoconf是一套非常全面,非常便携的工具的一部分,旨在使编写代码更容易,这些代码可以在各种目标系统上成功构建。有些人认为autoconf系统太复杂,无法解决你只用一个库函数造成的一个问题,但随着任何程序的增长,它可能会面临更多这样的障碍,并且为你的程序设置autoconf现在会放你处于一个更强大的未来地位。
从名为Makefile.in
的文件开始,其中包含:
CFLAGS=--ansi --pedantic -Wall -W
program: program.o
program.o: program.c
clean:
rm -f program.o program
以及名为configure.ac
的文件,其中包含:
AC_PREREQ([2.69])
AC_INIT(program, 1.0)
AC_CONFIG_SRCDIR([program.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for library functions.
AH_TEMPLATE([HAVE_ITOA], [Set to 1 if function atoi() is available.])
AC_CHECK_FUNC([itoa],
[AC_DEFINE([HAVE_ITOA], [1])]
)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
以及名为program.c
的文件,其中包含:
#include <stdio.h>
#include "config.h"
#ifndef HAVE_ITOA
/*
* WARNING: This code is for demonstration purposes only. Your
* implementation must have a way of ensuring that the size of the string
* produced does not overflow the buffer provided.
*/
void itoa(int n, char* p) {
sprintf(p, "%d", n);
}
#endif
int main(void) {
char buffer[100];
itoa(10, buffer);
printf("Result: %s\n", buffer);
return 0;
}
现在依次运行以下命令:
autoheader
:这会生成一个名为config.h.in
的新文件,我们稍后会需要这个文件。autoconf
:这会生成一个名为configure
./configure
:这会运行一些测试,包括检查你是否有一个正常工作的C编译器和,因为我们已经问过它,itoa
函数是否可用。它将结果写入文件config.h
以供日后使用。make
:这会编译并链接该程序。./program
:这最终运行程序。在./configure
步骤中,您会看到很多输出,包括:
checking for itoa... no
在这种情况下,您会看到config.h
查找包含以下行:
/* Set to 1 if function atoi() is available. */
/* #undef HAVE_ITOA */
或者,如果你做有atoi
可用,你会看到:
checking for itoa... yes
,这在config.h
:
/* Set to 1 if function atoi() is available. */
#define HAVE_ITOA 1
您会看到该程序现在可以阅读config.h
标题,并选择定义itoa
,如果它不存在。
是的,解决问题还有很长的路要走,但您现在已经开始使用一个非常强大的工具,可以通过多种方式为您提供帮助。
祝你好运!