我正在查看 errno.h 源代码,以查找变量 errno 是如何实现的,我预计它是 int 或类似的东西,但是当我查看 glibc errno.h 文件时,我发现了这一行
/* The error code set by various library functions. */
extern int *__errno_location (void) __THROW __attribute_const__;
# define errno (*__errno_location ())
这对我来说意味着 errno 不是 int,它是 int 函数,但是当我研究 glibc strtol 函数时,为了了解它如何与 errno 交互,我发现了这个
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
}
根据我对C的理解,errno将被替换为
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
(*__errno_location ()) = ERANGE;
}
这对我来说不合逻辑,因为我们无法为函数赋值 然后我在 strtol 中发现了这一行,这让我更加困惑
extern int errno;
现在 errno 将用作什么、int 或函数?
然后我去unix实现“https://opensource.apple.com/”
我发现了类似的东西,但没有
extern int errno;
所以基本上没有名为 errno 的变量
...这对我来说意味着 errno 不是 int,它是 int 函数,...
宏定义
# define errno (*__errno_location ())
导致 errno
被替换为该表达式,即:
_errno_location
,()
,然后是 *
来取消引用函数返回的指针。前一行
extern int *__errno_location (void) __THROW __attribute_const__;
声明 __errno_location
是一个返回 int *
的函数,而不是 int
。
...对我来说不合逻辑,因为我们无法为函数赋值...
它的工作方式是,
__errno_location()
返回指向int
的指针,而* __errno_location()
指的是int
。因此,您可以分配给该 int
,类似于此代码:
int *p = __errno_location(); // Set a pointer to an `int`.
*p = ERANGER; // Assign ERANGE to the `int` pointed to by `p`.
这对我来说不合逻辑,因为我们无法为函数赋值 然后我在 strtol 中发现了这一行,这让我更加困惑
它没有给函数赋值。
extern int *__errno_location (void) __THROW __attribute_const__;
# define errno (*__errno_location ())
__errno_location
返回指向 int
(*__errno_location ()) = ERANGE;
逻辑上等同于:
int *errno_ptr = __errno_location ();
*errno_ptr = ERANGE;