Случается, когда ваш скрипт пытается отправить HTTP-клиенту клиенту, но он уже был выведен ранее, что привело к тому, что заголовки уже отправлены на клиент.
Это E_WARNING
, и он не остановит сценарий.
Типичным примером может быть файл шаблона, подобный этому:
My Page
...
Функция session_start()
попытается отправить клиенту файлы cookie сеанса. Но PHP уже отправил заголовки, когда он написал элемент в выходной поток. Вам нужно будет переместить
session_start()
в верхнюю часть.
Вы можете решить эту проблему, пройдя через строки до код, запускающий предупреждение, и проверьте, где он выдается. Переместите любой заголовок, отправляющий код перед этим кодом.
Часто пропускаемый вывод - это новые строки после закрытия PHP ?>
. Считается стандартной практикой опускать ?>
, когда это последняя вещь в файле. Аналогичным образом, еще одной распространенной причиной этого предупреждения является то, что перед открытием перед ним появляется пустое пространство, строка или невидимый символ, в результате чего веб-сервер отправляет заголовки и пробел / новую строку, таким образом, когда PHP начинает синтаксический анализ, он не сможет для отправки любого заголовка.
Если в вашем файле содержится более одного кодового блока , у вас не должно быть пробелов между ними. (Примечание: у вас может быть несколько блоков, если у вас есть код, который был автоматически сконструирован)
Также убедитесь, что в вашем коде не указаны знаки байтового заказа, например, когда кодировка скрипта является UTF -8 с BOM.
Вопросы, относящиеся
Вы могли сделать что-то как:
typedef struct {
unsigned int c_idx;
} char_idx;
typedef struct {
unsigned int b_idx;
} byte_idx;
Затем Вы видели бы при использовании каждого:
char_idx a;
byte_idx b;
b.b_idx = a.c_idx;
Теперь более ясно, что они - различные типы, но все еще скомпилировали бы.
Для типов "дескриптора" (непрозрачные указатели), Microsoft использует прием объявления структур и затем typedef'ing указатель на структуру:
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
typedef struct name##__ *name
Затем вместо
typedef void* FOOHANDLE;
typedef void* BARHANDLE;
Они делают:
DECLARE_HANDLE(FOOHANDLE);
DECLARE_HANDLE(BARHANDLE);
Поэтому теперь, это работает:
FOOHANDLE make_foo();
BARHANDLE make_bar();
void do_bar(BARHANDLE);
FOOHANDLE foo = make_foo(); /* ok */
BARHANDLE bar = foo; /* won't work! */
do_bar(foo); /* won't work! */
Используйте линт. См. Splint:Types и сильная проверка типа .
Сильный тип, проверяющий часто, показывает программные ошибки. Шплинт может проверить примитивные типы C более строго и гибко, чем типичные компиляторы (4.1) и оказывает поддержку булев тип (4.2). Кроме того, пользователи могут определить абстрактные типы, которые обеспечивают сокрытие информации (0).
В C [только 116] различие между пользовательскими типами , который является осуществлен компилятором , является различием между структуры . Любое определение типа, включающее отличные структуры, будет работать. Ваш главный вопрос о дизайне , различные типы структуры должны использовать те же имена элемента? Если так, можно моделировать некоторый полиморфный код с помощью макросов и других приемов цинги. В противном случае Вы действительно посвящаете себя двум различным представлениям. Например, Вы хотите быть в состоянии к
#define INCREMENT(s, k) ((s).n += (k))
и использование INCREMENT
и на byte_idx
и на char_idx
? Тогда назовите поля тождественно.
Вы спросили о расширениях. Jeff Foster CQual очень хорош, и я думаю, что он мог сделать задание, которое Вы хотите.
Если бы Вы писали C++, то Вы могли бы сделать два тождественно определенных класса с различными именами, которые были обертками вокруг неподписанного интервала. Я не знаю о приеме, чтобы сделать то, что Вы хотите в C.
То, что вам нужно, называется "строгим определением типов" или "строгим определением типов".
Некоторые языки программирования [Rust, D, Haskell, Ada, ...] предоставляют некоторую поддержку для этого на уровне языка, C [++] - нет. Было предложение включить его в язык с именем "opaque typedef", но оно не было принято.
Однако отсутствие поддержки языка на самом деле не проблема. Просто оберните тип, который будет псевдонимом, в новый класс, имеющий ровно 1 член данных типа T. Большая часть повторений может быть исключена с помощью шаблонов и макросов. Этот простой прием так же удобен, как и в языках программирования с прямой поддержкой.
Использовать строгое определение типа, как определено в BOOST_STRONG_TYPEDEF