Я не особенно новичок в 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.<b>h</b> */ // ! 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;
}
(Замена стандартного нового оператора работает во всех вышеупомянутых случаях. Замена нового оператора является незаконной, я знаю.)
Шаблон легко увидеть, но кто-нибудь может предложить мне «стандартное» объяснение?
Почему я могу делать в файлах .c или .cc то, что не могу в файлах .h (переопределить старые typedefs, заменить функции, которые нельзя заменить)?
Спасибо за ответ. Я пропустил некоторый код, включая защиту заголовков. В последнем примере .cc я HTML закодировал << как & g t; & g t; по ошибке и забыл включить cstdlib.
Я исправил код, чтобы он компилировался. Тем не менее, еще одна вещь, которую я пропустил, была #define _NEW, что оказалось решающим. По-видимому, в GNU защита заголовка <new>определяет _NEW, поэтому мое определение здесь предотвратило включение стандартного нового заголовка, поэтому замена работала
m@m:~/Desktop/Library$ ./a.out
PLACEMENT NEW CALLED
OPERATOR NEW CALLED
Так что, да, единственное, что остается необъяснимым, это то, почему я могу многократно переписывать вещи в файлах .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) теперь кажется довольно очевидным. Я просто # определяю макрос охранника заголовка из стандартного X.h в свой X.h:).