我对 C/C++ 并不是特别陌生,但今天我发现了一些我没想到的东西。这在 gcc 中编译:
/* test.c */
#include <stddef.h> // !
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // NO ERROR
int
main(void)
{
typedef unsigned long int size_t; // NO ERROR
return 0;
}
这不会:
/* test.c */
#include <stddef.h>
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // NO ERROR
int
main(void)
{
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // ERROR
return 0;
}
这也不是:
/* test.h */ // ! header
typedef unsigned long int size_t;
typedef unsigned long int size_t; // ERROR
同样在 g++ 中编译:
/* test.h */ // ! header
#include <cstddef>
inline void* operator new(size_t, void* p) throw() { return p; }
这不会:
/* test.h */ // ! header
#include <new> // !
inline void* operator new(size_t, void* p) throw() { return p; } // ERROR
这样做:
/* test.cc */
#define _NEW
#include <new> // !
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
inline void* operator new(size_t size) throw() // NO ERROR EXPECTED
{
cout << "OPERATOR NEW CALLED" << endl;
return malloc(size);
}
inline void* operator new(size_t, void* p) throw() // NO ERROR
{
cout << "PLACEMENT NEW CALLED" << endl;
return p;
}
int main()
{
char *buffer[4];
int *i = new (buffer) int;
int *j = new int;
return 0;
}
(替换标准的 new 操作符在上述所有情况下都有效。替换替换的 new 操作符是非法的,我知道。)
很容易看到一种模式,但是有人可以给我一个“标准”的解释吗?为什么我可以在 .c 或 .cc 文件中做我在 .h 文件中不能做的事情(重新定义旧的 typedef,替换非法替换的函数)?
谢谢回复。我省略了一些代码,包括标题保护。在最后一个 .cc 示例中,我将 HTML 编码为 << 为 & gt ;> 错误地忘记包含 cstdlib。我已经修复了代码,所以它可以编译。然而,我忽略的另一件事是#define _NEW,它被证明是至关重要的。显然在 GNU 中,<new> 的标头保护定义了 _NEW,所以我在这里定义它阻止了标准新标头的包含,所以我替换工作了
m@m:~/Desktop/Library$ ./a.out 安置新呼叫 操作员新呼叫
所以,是的,唯一无法解释的是我为什么可以在 .c/.cc 文件中多次重新键入定义内容,但不能像这样在 .h 中重新键入:
/* test.c */
#include <stddef.h>
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // NO ERROR
int
main(void)
{
typedef unsigned long int size_t; // NO ERROR
return 0;
}
反正我也不想那样做,只是想知道。
编辑:谢谢,这真的回答了所有问题。将其更改为 xyz 不允许在给定范围内进行多个定义,这感觉不错。:) 我做这些小测试的原因是我正在为一个小型操作系统编写 C 和 C++ 的一个子集,但是由于我使用现有的库而没有删除任何东西来帮助我进行测试,所以我正在尝试弄清楚如何确保(1)我的代码在测试中被调用(例如我的新位置)和(2)我的代码不会与 GNU 库发生冲突。(1)的答案现在看起来很明显。我只是将标准 Xh 中的标头保护宏#define 到我的 Xh 中:)。