5.5.1 C函数的可移植性

大多数常用功能可能缺失、有缺陷或受到限制在一些架构上。本节试图对这些进行盘点可移植性问题。根据定义,此列表始终需要添加。Gnulib维护了一个更完整的列表项目(请参见格努利布),覆盖当前Posix函数在里面格努利布传统功能在里面格努利布、和Glibc函数在里面格努利布.请帮助我们保持Gnulib列表尽可能完整。

出口

在古代东道主身上,出口返回整数.这是因为出口早于空隙,有一个很长的回归传统整数.

在当前主机上,问题更可能是出口不是声明,这是由于某些C++问题引起的。出于这个原因我们建议测试程序不要调用出口,但从返回主要的而不是。

伊辛夫
伊斯南

在C99及更高版本中,isinf公司伊斯南宏。在某些系统上,只有宏可用(例如,HP-UX和Solaris 10),在上一些系统包括宏和函数(例如glibc 2.3.2),以及一些仅系统功能(例如IRIX 6)。在某些情况下这些函数在非标准头中声明,如<sunmath.h>并在非默认库中定义,如-流明-艾桑玛.

在C99及更高版本中,isinf公司伊斯南宏可以正确使用长双倍参数,但C99之前使用函数的系统通常假设双重的论据。在这样的系统上,isinf公司对于有限长双倍超出范围的参数双重的.

解决这些问题的最佳方法是使用Gnulib模块isinf公司是吗(请参见格努利布). 但重量更轻解决方案包括如下代码。

#包括<math.h>#如果ndef isnan#定义isnan(x)\(sizeof(x)==大小of(长双精度)?isnan_ld(x)\:sizeof(x)==大小of(双精度)?是南_d(x)\:isnan_f(x))静态int isnan_f(浮点x){return x!=x;}静态int isnandd(双x){return x!=x;}静态int isnan_ld(长双精度x){return x!=x;}#结尾#如果ndef isinf#定义isinf(x)\(sizeof(x)==大小of(长双精度)?isinf_ld(x)\:sizeof(x)==大小of(双精度)?isinf(x)\:isinf_f(x))静态int isinf_f(浮点x){return!isnan(x)&&isnan(x-x);}静态int isinfd(双x){return!isnan(x)&&isnam(x-x);}静态int isinf_ld(长双x){return!isnan(x)&&isnam(x-x);}#结尾

一些优化编译器错误地处理了这些定义,但系统存在该错误通常有许多其他浮点拐角符合性问题无论如何,这可能不值得担心。

malloc公司

C标准表示呼叫成功malloc(0)是实现依赖。它可以返回无效的或新的非空指针。后者更为常见(例如GNU C库),但不意味着通用。AC_FUNC_分配可用于坚持非-无效的(请参见特殊功能检查).

普京

Posix更喜欢环境变量普京; 除其他事项外,普京并非所有Posix实现都需要,但环境变量是。

Posix指定普京将给定字符串直接放入环境,但有些系统会复制它(例如。,glibc 2.0或BSD)。当制作副本时,删除环境变量可以不释放它,导致内存泄漏(例如,FreeBSD 4)。

在某些系统上普京(“FOO”)删除'FOO公司'来自环境,但这不是标准用法,它会转储核心在某些系统(例如AIX)上。

在MinGW上,一个电话普京(“FOO=”)删除'FOO公司'来自环境,而不是用空值插入它。

重新分配

打电话有问题重新分配大小为零。C标准表示重新分配(NULL,0)等于malloc(0),这意味着无法便携式地判断呼叫是否如果返回空指针,则成功。如果脉冲重复频率非空,C标准说重新分配(ptr,0)具有未定义的行为。

这个AC_FUNC_REALLOC公司宏可以避免这些可移植性问题,和Gnulib模块真实位置gnu避免更多这样的问题。请参见特殊功能检查.

信号处理程序

在大多数情况下,它使用起来更健壮信号作用当它是可用,而不是信号.

snprintf(打印)

在C99及更高版本中,如果输出数组不够大如果没有其他错误发生,snprintf(打印)vsn打印截断输出并返回应该具有的字节数已生产。一些古代系统返回截断长度(例如。,GNU C Library 2.0.x或IRIX 6.5),有些则为负值(例如,早期GNU C库版本)。

strerror或r

Posix指定strerror或r返回一个整数,但很多系统(例如,GNU C Library版本2.36)提供了不同版本返回字符*.AC_FUNC_STRERROR_R可以检测出正在使用的设备(请参见特殊功能检查).

斯特伦

AIX4.3提供了一个损坏的版本,该版本生成以下结果:

strnlen(“foobar”,0)=0strnlen(“foobar”,1)=3strnlen(“foobar”,2)=2strnlen(“foobar”,3)=1strnlen(“foobar”,4)=0strnlen(“foobar”,5)=6strnlen(“foobar”,6)=6strnlen(“foobar”,7)=6strnlen(“foobar”,8)=6strnlen(“foobar”,9)=6
系统控制

_SC_页面大小是标准的,但有些较旧的系统(例如HP-UX9) 有_SC_页面_大小相反。这可以用测试#ifdef(如果定义).

取消链接

Posix规范说取消链接导致给定文件只有在没有更多打开的文件句柄后才删除但是,非Posix主机无法满足此要求,一些DOS变体甚至会损坏文件系统。

删除环境变量

在MinGW上,删除环境变量不可用,但变量'FOO公司可以通过呼叫删除普京(“FOO=”),如下所述普京以上。

va_副本

C99及更高版本提供va_副本用于复制列表(_L)变量。它可能在较旧的环境中可用也是,虽然可能是__va_副本(例如。,通用控制中心严格地C99之前的模式)。这些可以用测试#ifdef(如果定义).回退到memcpy(&dst,&src,sizeof(va_list))给出最大值可移植性。

值列表(_L)

值列表(_L)不一定只是一个指针。它可以是结构(例如。,通用控制中心在Alpha上),这意味着无效的不可携带。也可以是数组(例如。,通用控制中心在一些PowerPC配置),这意味着它可以作为功能参数有效地通过引用调用,库例程可能会修改值返回调用方(例如。,vsn打印在GNU C库中2.1).

签署>>

通常为C>>有符号类型的右移复制高位,进行所谓的“算术”移位。但要小心因为标准C不需要这种行为。在一些平台上(例如,默认情况下为Cray C)零位移位,与无符号类型。

整数/

C将有符号整数的商截断为零,产生与Fortran相同的结果。然而,在C99标准之前允许C实现达到商的下限或上限在某些情况下。几乎没有任何实现利用了这一点然而,自由可能不值得担心这个问题现在。