【问题标题】:What is the difference between crypt in unistd.h and crypt.h?unistd.h 和 crypt.h 中的 crypt 有什么区别?
【发布时间】:2019-02-01 07:09:51
【问题描述】:

背景

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 声明可以正常工作,这会让人更加困惑。

【问题讨论】:

  • 这是一个关于 C 的问题,而不是关于 Linux 使用或管理的问题。

标签: compilation c posix crypt


【解决方案1】:

这是两个声明,而不是两个定义。头文件的内容对包含哪个函数定义没有影响:这是由链接器决定的。 crypt 函数在 Unix C 标准库中只有一个定义,它是 crypt 在 libcrypt.a 或 libcrypt.so 中指向的任何符号(取决于您是静态链接还是动态链接)。

由于这两个声明是兼容的,程序通过哪个头文件并不重要。如果两个声明都被处理也很好:一个程序可以包含任意数量的函数声明,只要它们兼容。无需详细说明(请参阅 C 语言规范),如果两个函数声明具有相同的返回类型、相同数量的参数和每个参数的相同类型,则它们是兼容的。声明中给出的参数名称并不重要。

【讨论】:

  • 这就是我的想法,但我知道其中一些东西是内部定义的,并且做了一些深奥的巫术(至少使用 c99.h 魔法)。如果它们是相同的定义,为什么unistd.h version not work then (my other question)
  • crypt 函数内部未定义。它是在库中定义的,而不是编译器本身可以为其生成代码的那些函数之一。 deep voodoo 用于有条件地包含 声明,而不是定义。声明此函数的两个标头使用不同的预处理器保护。要定义哪些预处理器符号以从 unistd.h 获取声明是您的另一个问题。
【解决方案2】:

你应该忽略unistd.h。该声明是为了与 POSIX 兼容,但当 GLIB 迁移到 libxcrypt 以独立于 glibc 开发这些功能时,他们删除了 crypt 的定义。这意味着您仍然可以获得 ABI 兼容性,但必须链接到 crypt。你可以阅读更多关于here

glibc 中的可用性

crypt ()、encrypt () 和 setkey () 函数是用于加密的 POSIX.1-2008 XSI 选项组的一部分,并且是可选的。如果接口不可用,则符号常量 _XOPEN_CRYPT 未定义或定义为 -1,并且可以在运行时使用 sysconf () 进行检查。

如果下游发行版已从 glibc crypt 切换到 libxcrypt,则可能会出现这种情况。在此类发行版中重新编译应用程序时, 用户必须检测_XOPEN_CRPYT 是否不可用,并在函数原型中包含 crypt.h;否则libxcrypt 是兼容 ABI 的直接替代品。

至于为什么即使链接定义也不用下拉

#define _XOPEN_VERSION 700
#define _POSIX_VERSION 200809L
#define __USE_MISC 1
#define _XOPEN_SOURCE

那里发生了一些事情

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

如果你想从unistd.h 中拉入crypt.h 的声明,你必须定义_GNU_SOURCE! 从man page of crypt.h 引用的这两个示例做同样的事情,无论您包括unistd.h 还是crypt.h,您还必须在当代版本的glibc 中定义_GNU_SOURCE。

所以你可以这样做,

#define _GNU_SOURCE
#include <unistd.h>

或者,

#define _GNU_SOURCE
#include <crypt.h>

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    相关资源
    最近更新 更多