crypt
有两个定义,from the docs,
其中一个使用unistd.h
#define _XOPEN_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
这被定义为
#ifdef __USE_MISC
extern char *crypt (const char *__key, const char *__salt)
__THROW __nonnull ((1, 2));
#endif
其中一个使用GNU crypt.h
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <crypt.h>
这被定义为
extern char *crypt (const char *__phrase, const char *__salt)
__THROW __nonnull ((1, 2));
在第一个示例(unistd.h
)中使用定义进行编译时
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
int main()
{
printf("%s", crypt("foobar", "sa"));
}
我遇到错误
In function ‘main’:
warning: implicit declaration of function ‘crypt’; did you mean ‘chroot’? [-Wimplicit-function-declaration]
printf("%s", crypt("foobar", "sa"));
^~~~~
chroot
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s", crypt("foobar", "sa"));
~^ ~~~~~~~~~~~~~~~~~~~~~
%d
出于绝望,我尝试添加它。
#define _XOPEN_VERSION 700
#define _POSIX_VERSION 200809L
#define __USE_MISC 1
在Ubuntu Trusty 14.04上,我相信使用unistd.h
声明可以很好地解决这个问题,
答案 0 :(得分:3)
这是两个声明,而不是两个定义。头文件的内容对包含函数的定义没有影响:这由链接器确定。在Unix C标准库中,crypt
函数只有一个定义,无论crypt
或libcrypt.a
中的符号libcrypt.so
指向什么(取决于您是否静态链接)或动态)。
由于这两个声明是兼容的,所以程序通过哪个标头并不重要。如果两个声明都被处理也很好:一个程序可以包含任意数量的函数声明,只要它们兼容即可。无需详细说明(请参阅C语言规范),如果两个函数声明具有相同的返回类型,相同数量的参数以及每个参数相同的类型,则它们是兼容的。声明中给出的参数名称不重要。
答案 1 :(得分:0)
您应该忽略unistd.h
。该声明是为了实现POSIX兼容性,但是GLIB在将crypt
迁移到libxcrypt
以便隔离glibc来开发这些功能时,已删除了crypt
的定义。这意味着您仍然可以获得ABI兼容性,但必须在crypt ()
中进行链接。您可以了解有关here
glibc中的可用性
encrypt ()
,setkey ()
和_XOPEN_CRYPT
函数是POSIX.1-2008 XSI用于加密的选项组的一部分,并且是可选的。如果接口不可用,则符号常量sysconf ()
可能没有定义或定义为-1,可以在运行时使用libxcrypt
进行检查。如果下游发行版已从glibc crypt切换到
_XOPEN_CRPYT
,则可能是这种情况。在此类发行版中重新编译应用程序时, 用户必须检测libxcrypt
是否不可用,并为函数原型包含crypt.h;否则,#define _XOPEN_VERSION 700 #define _POSIX_VERSION 200809L #define __USE_MISC 1 #define _XOPEN_SOURCE
是与ABI兼容的直接替换。
关于为什么即使您链接该定义也不会被
下拉unistd.h
那里有一些事情发生
__USE_MISC
中唯一重要的标头是unistd.h
。features.h
包括undef
s the __USE_
macros to start with a "clean slate" __USE_MISC
_GNU_SOURCE
的唯一方法是定义crypt.h
。如果要从unistd.h
中提取_GNU_SOURCE
的声明,则必须定义unistd.h
! 从man page of crypt.h
引用的这两个示例做同样的事情,无论您是包含crypt.h
还是_GNU_SOURCE
,您还必须在当代版本的glibc中定义#define _GNU_SOURCE
#include <unistd.h>
所以你可以做,
#define _GNU_SOURCE
#include <crypt.h>
或者
crypt
但是因为您必须链接到-lcrypt
(crypt.h
),所以我建议使用DataFrame
中的声明以保持理智。