- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
阅读 -I
的细则在 GCC 中切换,我很震惊地发现在命令行上使用它会覆盖系统包括。来自 preprocessor docs
"You can use
-I
to override a system header file, substituting your own version, since these directories are searched before the standard system header file directories."
他们似乎没有撒谎。在具有 GCC 7 的两个不同 Ubuntu 系统上,如果我创建文件 endian.h
:
#error "This endian.h shouldn't be included"
...然后在同一目录中创建 main.cpp
(或main.c,相同的区别):
#include <stdlib.h>
int main() {}
然后用 g++ main.cpp -I. -o main
编译(或clang,相同的区别)给了我:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:194:0,
from /usr/include/stdlib.h:394,
from /usr/include/c++/7/cstdlib:75,
from /usr/include/c++/7/stdlib.h:36,
from main.cpp:1:
./endian.h:1:2: error: #error "This endian.h shouldn't be included"
所以 stdlib.h 包含这个 types.h 文件,它在第 194 行只是说 #include <endian.h>
.我明显的误解(也许是其他人的误解)是尖括号可以防止这种情况发生,但是 -I 比我想象的要强大。
虽然不够强足够,因为你甚至无法通过在命令行中粘贴/usr/include 来修复它,因为:
"If a standard system include directory, or a directory specified with
-isystem
, is also specified with-I
, the-I
option is ignored. The directory is still searched but as a system directory at its normal position in the system include chain."
确实,g++ -v main.cpp -I/usr/include -I. -o main
的详细输出将/usr/include 留在列表底部:
#include "..." search starts here:
#include <...> search starts here:
.
/usr/include/c++/7
/usr/include/x86_64-linux-gnu/c++/7
/usr/include/c++/7/backward
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
让我感到惊讶。我想这是一个问题:
大多数项目使用 -I
的正当理由是什么?考虑到这个极其严重的问题? 您可以根据偶然的名称冲突覆盖系统上的任意 header 。几乎每个人都不应该使用-iquote
代替?
最佳答案
-I
有什么正当理由?超过 -iquote
? -I
是标准化的(至少由 POSIX ),而 -iquote
不是。 (实际上,我使用的是 -I
,因为 tinycc(我希望我的项目编译的编译器之一)不支持 -iquote
。)
如何使用 -I
管理项目考虑到危险?您将包含包含在一个目录中并使用 -I 添加包含该目录的目录。
includes/mylib/endian.h
-Iincludes
#include "mylib/endian.h" //or <mylib/endian.h>
这样,只要您不与 mylib
发生冲突即可名称,你不会冲突(至少就标题名称而言)。
关于c++ - 考虑到危险,为什么项目使用 -I include 开关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53154898/
编辑:澄清一下,我明白为什么这段代码不起作用,我并不是要修复它,而是想了解如果这段代码可以在没有语义错误的情况下编译会有什么危险。 我发现下面的代码会导致静态语义错误。我知道这是因为 std::lis
我想知道 C# 枚举以及重复值会发生什么。我创建了以下小程序来测试: namespace ConsoleTest { enum TestEnum { FirstElem
正如我在另一个 SO 问题中指出的那样,我遇到了 this article .当我通过 MSVC7.1 编译 boost 1.40 时出现了这个问题,并且弹出了几个 C4251 警告。 现在,在阅读上
我有以下弹出窗口代码(客户端请求)。它使用 eval ,我知道这是危险的。有没有办法重写下面的脚本,使其不使用 (eval)? /* exported popup_default , popup_he
NTFS 文件可以有对象 ID。可以使用 FSCTL_SET_OBJECT_ID 设置这些 ID .然而,msdn article说: Modifying an object identifier c
我一直在学习命令行参数解析。关于这个已经有很长的线索了,我不想在这里挑起一个: Using getopts in bash shell script to get long and short com
这个问题在这里已经有了答案: How to configure ContextMenu buttons for delete and disabled in SwiftUI? (4 个回答) 4 个月
为什么在 linux 的中断处理程序中禁止 printk 或 (I/O)。?在什么情况下中断处理程序中的 I/O 会导致 linux 系统中的死锁? 最佳答案 关于 printk(),它是侵入性的。例
不是 Invoking virtual function and pure-virtual function from a constructor 的重复项: 以前的问题与 C++ 03 相关,而不是
我正在使用 lateinit 属性以避免使用 ?运算符(operator)。我有很多 View 属性是第一次在 getViews() 函数中分配的。如果该功能不存在,我的应用程序将与来自 Kotlin
我最近在使用 fputs 时遇到了问题:当使用 fputs 在文本文件中打印一些字符串时,我碰巧得到了除 A-Z、a-z、0-9 之外的其他字符(不属于字符串的字符) .我绝对确保所有字符串都以空字符
在仅包含字节数组的结构上使用 #pragma pack(1) 是否危险/有风险?例如。这个: #pragma pack(1) struct RpcMessage { uint8_t proto
我是一名优秀的程序员,十分优秀!