Я наткнулся на приведенный ниже код, который меня сбил с толку:
union
{
struct
{
uint32_t Id;
uint8_t a_data[];
}vendor;
uint8_t avp[0];
}data;
Это нормально компилируется с g ++ 7.2.1, но я не могу понять почему. Как нет необходимости указывать размер при определении a_data? Как у avp может быть нулевой размер?
Это гибкий элемент массива и технически не является частью C++ (это функция только для C).
Некоторые компиляторы (особенно GCC) с радостью добавляют функции из C как расширения в C++. Таким образом, он не переносится, и вам следует по возможности избегать такого кода.
Это потому, что GCC - это компилятор C, и эта функция ISO C99 ... G ++ - это компилятор C++, который сохраняет функции GCC. Интересно, как они относятся к строгому сглаживанию, когда имеют дело с этим. По крайней мере, три большие платформы используют это расширение, WIndows API написан с его использованием, и я поймал, что мои коллеги переносят это в своем коде с Windows на Linux. Потому что они думают, что это стандарт. Но Windows API также написан с функциями, имеющими несколько точек входа.
Это ужасный способ инициализировать объект структуры, но его очень приятно знать!
@ Swift-FridayPie Я использую термин «GCC» как сокращение от «GNU Compiler Collection» (так он официально используется). И несмотря ни на что, gcc
и g++
программы могут компилировать исходные файлы как на C, так и на C++. Разница между интерфейсными программами gcc
и g++
заключается в некотором флаге, который они передают фактическому компилятору и компоновщику.
@ Frederik.L было время, когда в libjpeg была уязвимость, основанная на использовании этой функции. Так легко описать формат файла, в котором фиксированные заголовки располагались в начале. Проблема в том, как после этого управлять доступом к памяти.
a_data[]
является стандартом C99 и не всегда поддерживается компиляторами C++. Использованиеuint8_t avp[0];
в качестве гибкого члена является исключительно расширением GCC для той же цели и не должно использоваться вообще. Это восходит к 1969 году. Некоторые другие компиляторы могут рассматривать его как массив нулевого размера, и любой доступ будет вне границ.