Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在使用gnu90和c90标准编译时,strerror\u r的行为为何会有所不同?_C_Gcc_Gnu_C89 - Fatal编程技术网

在使用gnu90和c90标准编译时,strerror\u r的行为为何会有所不同?

在使用gnu90和c90标准编译时,strerror\u r的行为为何会有所不同?,c,gcc,gnu,c89,C,Gcc,Gnu,C89,这是我的节目 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> int main() { char errbuf[256]; errno = 0; strtoul("99999999999999999999999999999999999999999999", NULL, 0);

这是我的节目

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int main()
{
        char errbuf[256];

        errno = 0;
        strtoul("99999999999999999999999999999999999999999999", NULL, 0);
        strerror_r(errno, errbuf, sizeof errbuf);
        printf("strerror_r: %s\n", errbuf);

    return 0;
}
但是当我用
-std=c90
-std=c99
编译它时,我得到一个警告,我没有看到
strerror\u r
将字符串放入
errbuf

lone@debian:~/lab/linux$ rm -f a.out && gcc -std=c90 -Wall -Wextra -pedantic foo.c && ./a.out
foo.c: In function ‘main’:
foo.c:12:2: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
  strerror_r(errno, errbuf, sizeof errbuf);
  ^
strerror_r:
lone@debian:~/lab/linux$ rm -f a.out && gcc -std=c99 -Wall -Wextra -pedantic foo.c && ./a.out
foo.c: In function ‘main’:
foo.c:12:2: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
  strerror_r(errno, errbuf, sizeof errbuf);
  ^
strerror_r:

当我使用
-std=c90
-std=c99
时,会出现什么问题?

使用
-std=c89
时,您要求实现只提供ISO 9899:1989中标识符部分的声明。标识符
strerror\r
不是C89(或C99)的一部分,因此没有原型。因此,您会收到关于隐式声明的警告


如果您查看相关标题,您可能会发现strerror_r原型埋在
\ifdef
s的迷宫中。
-std
选项更改影响原型可见性的预定义宏集。

strerror\r(3)表示:

兼容XSI的strerror_r()是便携式应用程序的首选。它返回用户提供的缓冲区buf中长度为buflen的错误字符串

GNU特定的strerror_r()返回一个指针,指向包含错误消息的字符串。这可以是指向函数存储在buf中的字符串的指针,也可以是指向某个(不可变)静态字符串的指针(在这种情况下,buf未使用)。如果函数将字符串存储在buf中,则最多存储buflen字节(如果buflen太小且errnum未知,则字符串可能会被截断)。该字符串始终包含一个终止的空字节

因此,这不仅仅是声明是否可见的问题(这本身就是一个相当大的问题——当您收到“隐式声明”警告时,您不应该期望程序工作)。这也是您调用的函数版本的问题。GNU版本有时返回指向库中常量字符串的指针,而不是将字符串复制到调用方提供的缓冲区


strerror\r
的基本用途不是“我希望字符串在此缓冲区中”;这是“我想要一个以后不会被库覆盖的字符串。”

在中找不到
strerror\r
的定义。但这并不能解释为什么输出不同,是吗?是的。如果没有原型,您的实现会在strerror_r()的两个不兼容版本之间进行选择。string.h中的注释解释道:有两种风格的
strerror\u
,GNU返回字符串,可以使用也可以不使用提供的临时缓冲区,POSIX one将字符串填充到缓冲区中。要使用POSIX版本,需要
-D_XOPEN_SOURCE=600
-D_POSIX_C_SOURCE=200112L
而不使用
-D_GNU_SOURCE
,否则首选GNU版本。那么,在第一种情况下使用哪个版本(gnu90/gnu99)?我假设是GNU版本。因此,在第二种情况下,使用posix版本,它填充缓冲区中的字符串。那么,为什么不打印呢?如果我正确解释了宏迷宫,gnu90/99将使用XPG版本,即用一个字符串填充BUF,该字符串描述ERRNUM中
errno
代码的含义。。您可以通过运行
gcc-E-std=gnu90-x c-dM string.h
来查询有效的宏。请注意,许多系统上strerror_r()的手册页错误地声称它是C99的一部分。不是。
lone@debian:~/lab/linux$ rm -f a.out && gcc -std=c90 -Wall -Wextra -pedantic foo.c && ./a.out
foo.c: In function ‘main’:
foo.c:12:2: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
  strerror_r(errno, errbuf, sizeof errbuf);
  ^
strerror_r:
lone@debian:~/lab/linux$ rm -f a.out && gcc -std=c99 -Wall -Wextra -pedantic foo.c && ./a.out
foo.c: In function ‘main’:
foo.c:12:2: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
  strerror_r(errno, errbuf, sizeof errbuf);
  ^
strerror_r: