Ре @ Адам Розенфилд: Союз добьется выравнивания до тех пор, пока поставщик персонажа * не начнет делать что-то подобное.
Может быть полезно отступить и выяснить, о чем все это.
Основой для правила наложения имен является тот факт, что компиляторы могут размещать значения разных простых типов на разных границах памяти для улучшения доступа, и что в некоторых случаях аппаратное обеспечение может требовать такого выравнивания, чтобы вообще иметь возможность использовать указатель. Это также может проявляться в структурах, где имеется множество элементов разных размеров. Структура может быть начата на хорошей границе. Кроме того, компилятор может по-прежнему вводить слабые фрагменты во внутреннюю часть структуры, чтобы обеспечить правильное выравнивание элементов структуры, которые в этом нуждаются.
Учитывая, что компиляторы часто имеют опции для управления тем, как все это обрабатывается, или нет, вы можете видеть, что есть много способов, которыми могут возникнуть неожиданности. Это особенно важно знать при передаче указателей на структуры (приведенные как char * или нет) в библиотеки, которые были скомпилированы для получения различных соглашений о выравнивании.
А как насчет символа *?
Предположение о char * заключается в том, что sizeof (char) == 1 (относительно размеров всех других значимых данных) и что для указателей char * нет требования выравнивания. Таким образом, настоящий char * всегда можно безопасно передавать и успешно использовать, не заботясь о выравнивании, и это касается любого элемента массива char [], выполнения ++ и - на указателях и так далее. (Как ни странно, void * не совсем то же самое.)
Теперь вы сможете увидеть, как если вы перенесете какие-то структурные данные в массив char [], который не был выровнен должным образом, попытка привести к указателю, который требует выравнивания, может быть серьезной проблема.
Если вы сделаете объединение массива char [] и структуры, компилятор будет соблюдать самое требовательное выравнивание (т. Е. Выравнивание структуры). Это будет работать, если поставщик и потребитель эффективно используют соответствующие объединения, так что приведение struct * к char * и обратно работает просто отлично.
В этом случае я хотел бы надеяться, что данные были созданы в аналогичном объединении до того, как указатель на них был приведен к типу char * или они были перенесены любым другим способом в виде массива байтов sizeof (char). Также важно убедиться, что любые параметры компилятора совместимы между библиотеками и вашим собственным кодом.