Когда стандарт 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
для его использования. Важно не то, что Стандарт определяет поведение действий, выполняемых с использованием макросов и функций из стандартной библиотеки, а то, что реализация гарантирует, что поведение таких макросов и функций соответствует требованиям.
person
supercat
schedule
09.08.2015
offsetof
macro, который работает должным образом. Компилятор также может реализоватьmemmove()
со сравнением, которое привело бы к неопределенному поведению, если бы оно было в пользовательском коде. Все делают. - person Pascal Cuoq   schedule 22.06.2011offsetof
, который вы можете использовать вместо него. - person Toby Speight   schedule 26.07.2018