Когда в стандарте C указано, что определенные действия вызывают неопределенное поведение, это обычно не означает, что такие действия запрещены, а скорее, что реализации могут свободно определять последующее поведение или нет, как они считают нужным.Следовательно, реализации могли бы свободно выполнять такие действия в случаях, когда Стандарт требует определенного поведения, тогда и только тогда, когда реализации могут гарантировать, что поведение для этих действий будет соответствовать тому, что Стандарт требует .Рассмотрим, например, следующую реализацию strcpy:
char *strcpy(char *dest, char const *src)
{
ptrdiff_t diff = dest-src-1;
int ch;
while((ch = *src++) != 0)
src[diff] = ch;
return dest;
}
Если src
и dest
не связаны между собой указателями, вычисление dest-src
приведет к неопределенному поведению.Однако на некоторых платформах соотношение между char*
и ptrdiff_t
таково, что для любого char* p1, p2
вычисление p1 + (p2-p1);
всегда будет равно p2
.На платформах, которые дают такую гарантию, приведенная выше реализация strcpy
будет законной (а на некоторых таких платформах может быть быстрее любой приемлемой альтернативы).Однако на некоторых других платформах такая функция всегда может завершаться ошибкой, за исключением случаев, когда обе строки являются частью одного и того же выделенного объекта.
Тот же принцип применяется к макросу offsetof
.Не требуется, чтобы компиляторы предлагали какой-либо способ получить поведение, эквивалентное offsetof
(кроме фактического использования этого макроса) Если модель компилятора для арифметики указателей позволяет получить требуемое поведение offsetof
с помощью ->
оператор на нулевом указателе, тогда его макрос offsetof
может сделать это.Если компилятор не будет поддерживать какие-либо попытки использовать ->
для чего-либо, кроме допустимого указателя на экземпляр типа, тогда ему может потребоваться определить встроенную функцию, которая может вычислять смещение поля, и определить макрос offsetof
дляиспользуйте это.Важно не то, чтобы Стандарт определял поведение действий, выполняемых с использованием макросов и функций стандартной библиотеки, а то, что реализация гарантирует, что поведение таких макросов и функций соответствует требованиям.