检查系统是否实现了某个function

我正在创建一个跨系统的应用程序。 例如,它使用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); 

我知道我可以检查宏是否是预定义的,如果没有定义它们:

 #ifndef _SOME_MACRO #define _SOME_MACRO 45 #endif 

有没有办法检查C函数是否已预先实现,如果没有,请实现它? 或者只是简单地实现一个function?

我假设你正在使用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在标准库中不可用,则将链接此文件。 你可以自信地编译它是否可用。

鉴于您已经编写了自己的itoa() ,我建议您重命名并在任何地方使用它。 至少你确定你会在所有平台上获得相同的行为,并避免链接问题。

不要忘记在您的代码的评论中解释您的选择…

Ajay Brahmakshatriya的建议是一个很好的建议 ,但不幸的是MinGW在我检查后不支持弱定义(例如,参见https://groups.google.com/forum/#!topic/mingwusers/44B4QMPo8lQ )。

但是,我认为弱引用在MinGW中起作用。 拿这个最小的例子:

 #include  #include  #include  __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:没有itoa

这里有两个非常重要的相关要点:“不要这样做”这一行:

  • 不要使用atoi因为它不安全 。
  • 不要使用atoi因为它不是标准function,并且有很好的标准function(例如snprintf )可以做你想要的。

但是,把所有这些放在一边,我想向您介绍autoconf ,它是GNU构建系统的一部分 。 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  #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; } 

现在依次运行以下命令:

  1. autoheader :这会生成一个名为config.h.in的新文件,我们稍后会需要它。
  2. autoconf :这会生成一个名为configure的配置脚本
  3. ./configure :这会运行一些测试,包括检查你是否有一个正常工作的C编译器, 并且因为我们已经问过它, itoa函数是否可用。 它将其结果写入文件config.h以供日后使用。
  4. make :编译并链接程序。
  5. ./program :这最终运行程序。

./configure步骤中,您将看到相当多的输出,包括:

 checking for itoa... no 

在这种情况下,您将看到config.h find包含以下行:

 /* 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如果它不存在)。

是的,解决问题还有很长的路要走,但现在您已经开始使用一个非常强大的工具,可以通过多种方式为您提供帮助。

祝好运!