与`g++有关wexitstatus的奇怪行为4.9.4`
下面的此代码段确实编译了,
#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>
int main()
{
int ret = 0xFFFF;
std::cout << WEXITSTATUS(ret);
}
而此代码段的确没有使用 g ++ 4.9.4
:
#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>
int main()
{
std::cout << WEXITSTATUS(0xFFFF);
}
这是编译器抱怨的内容:
In file included from /usr/include/x86_64-linux-gnu/sys/wait.h:77:0,
from t.cpp:2:
t.cpp: In function ‘int main()’:
t.cpp:7:22: error: lvalue required as unary ‘&’ operand
std::cout << WEXITSTATUS(0xFFFF);
^
这是有关编译器的详细信息:
g++ --version
g++ (Ubuntu 4.9.4-2ubuntu1~16.04) 4.9.4
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
编译 器的详细信息: ubuntu16.04通过以下命令
sudo apt-get install gcc-4.9
sudo apt-get install g++-4.9
sudo update-alterntives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20
sudo update-alterntives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20
注: 我必须使用G ++ -4.9,我别无选择。
奇怪的是,我无法在 godbolt.org
上重现上述现象。它在godbolt.org上编译带有 gcc 4.9.3.3
() GCC 4.9.4
不可用)。
这是 g ++ -e -e the_said_code_snippet_does_not_compile.cpp
的输出
//omit
# 4 "t.cpp" 2
int main()
{
std::cout << ((((*(const int *) &(0xFFFF))) & 0xff00) >> 8);
}
。
更新 :
我现在可以重现错误!请参阅此链接。
更新 :
这只是一个简化的示例。我实际上面对的是 wexitstatus(pclose(fp))
没有编译。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
wexitstatus
宏是C标准库实现的问题,而不是编译器本身。通常(对于GCC),编译器不提供C标准库实施。这是一个独立的软件包。包括Ubuntu在内的大多数Linux发行版都使用GLIBC作为C标准库实现。
在GLIBC直到版本2.23(包含)中,使用C ++和
__ USE_MISC
已设置(请参见下面的提示链接):宏的实际实现在
__ wexitstatus
中,但是使用wait_int 似乎是为了支持
Wait
接口的非posix“ Union Wait ”变体。通过此定义,宏无法使用prvalue,因为它试图获取status
的地址。在2016年,带有支持< em>联合等待 - 根据
News
在1990年代初提出的输入 - 已被删除,现在的定义也很简单,它也将与Prvalue一起使用。
似乎Ubuntu 16.04在更改之前仍使用GLIBC版本,这并不奇怪,因为它在提交时发布。
我不知道Posix对是否应该使用
int
rvalue而不是变量的名称使用宏。该
WexitStatus
不能总是直接在对pclose
的调用上使用。显然,上述扩展现在不再存在于glibc中了,它也存在于(某些?)BSD中(并且可能源自它们?)。参见例如这个问题,答案还表示对Posix-Compliance的怀疑。但是,链接的问题中提到的OpenBSD也在2014年删除了 Union等待。 Noreferrer“> ChangElog 自4.3BSD(1986年发行)以来,它已被弃用。The
WEXITSTATUS
macro is a matter of the C standard library implementation, not the compiler per se. Typically (and in the case of GCC) the compiler doesn't supply the C standard library implementation. It is an independent package.Most Linux distributions, including Ubuntu, use glibc as C standard library implementation.
In glibc until version 2.23, inclusive, the macro was defined in the following way when using C++ and
__USE_MISC
is set (see commit link below):The actual implementation of the macro is inside
__WEXITSTATUS
, but the use of__WAIT_INT
seems to be for the purpose of supporting the non-POSIX "union wait" variant of thewait
interface. With this definition, a prvalue cannot be used with the macro, because it tries to take the address ofstatus
.In 2016, with commit b49ab5f4503f36dcbf43f821f817da66b2931fe6 support for union wait - according to the
NEWS
entry deprecated in the early 1990s - has been removed and now the definition is simplyNow it would work with a prvalue as well.
It seems that Ubuntu 16.04 still uses a glibc version from before that change, which isn't surprising since it was released at the time of the commit.
I don't know what POSIX has to say about whether or not it should be possible to use the macro with a
int
rvalue rather than the name of a variable.That
WEXITSTATUS
can't always be used directly on a call topclose
seems to be known issue. Apparently the above-mentioned extension, which is now not present in glibc anymore, was (is?) also present in (some?) BSDs (and may originate from them?). See e.g. this question, in which the answer also expresses doubts about POSIX-compliance. However, OpenBSD, mentioned in the linked question, also removed union wait in 2014. According to the changelog it had been deprecated since 4.3BSD (released 1986).这看起来像是宏观的奇数实现,导致了操作员优先级的问题。通常情况下应该是这样的:
现在,如果它是(结果是完全错误的),
您会遵循顺序:
尽管我无法想象存在这种破裂的实施可能存在吗?
处理的代码片段表明,宏假设
状态
是返回至少一个prvalue的表达式,人们可以将其施放到const int
的“魔术”中。地址运营商遇到错误的操作数发生了错误。本质上,假设这些是从文档中描述的特定来源返回的值,则该宏不能仅与表达式或变量一起使用常数。
That looks like an oddball implementation of macro, causing problems with operator precedence. Usually it should be something like this:
now if it is (and completely wrong as result)
You wold get following order:
Though I can't imagine that such broken implementation could exist?
The processed code snippet shows that macro assumes
status
to be an expression returning at least a prvalue, something one can get address of and "magic" of casting it toconst int
.The error happens from address operator getting a wrong operand. Essentially this macro cannot work with a constant only with expression or variable, assuming that those are values returned from particular source described in documentation.