unistd.h和crypt.h中的crypt有什么区别?

时间:2019-02-01 07:09:51

标签: compilation c posix crypt

背景

crypt有两个定义,from the docs,

  1. 其中一个使用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
    
  2. 其中一个使用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声明可以很好地解决这个问题,

2 个答案:

答案 0 :(得分:3)

这是两个声明,而不是两个定义。头文件的内容对包含函数的定义没有影响:这由链接器确定。在Unix C标准库中,crypt函数只有一个定义,无论cryptlibcrypt.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

那里有一些事情发生

  1. __USE_MISC中唯一重要的标头是unistd.h
  2. features.h包括undefs the __USE_ macros to start with a "clean slate"
  3. 中的__USE_MISC
  4. 定义_GNU_SOURCE的唯一方法是定义crypt.h

如果要从unistd.h中提取_GNU_SOURCE的声明,则必须定义unistd.hman page of crypt.h引用的这两个示例做同样的事情,无论您是包含crypt.h还是_GNU_SOURCE,您还必须在当代版本的glibc中定义#define _GNU_SOURCE #include <unistd.h>

所以你可以做,

#define _GNU_SOURCE
#include <crypt.h>

或者

crypt

但是因为您必须链接到-lcryptcrypt.h),所以我建议使用DataFrame中的声明以保持理智。