Что подразумевается под самым ограничительным типом в C?

В книге «Язык программирования C» говорится о «самом ограничительном типе» в разделе 8.7 « Пример» – «Аллокатор хранения» :

Хотя машины различаются, для каждой машины существует наиболее ограничительный тип: если наиболее ограничительный тип может храниться на определенном адресе, могут быть и другие типы. На некоторых машинах наиболее ограничительный тип – double ; на других, int или long хватает.

В своем коде header union выравнивается с использованием типа long .

Что подразумевается под самым ограничительным типом? Возможно, это самый большой тип (например, double ), или есть другой подход?

ЦП часто требуют (или работают более эффективно, если) определенные типы данных хранятся на адресах, кратных некоторому (силе-двух) значения. Это значение называется выравниванием данных. Например, ЦП может требовать, чтобы четырехбайтовые целые числа сохранялись на адресах, которые кратно четырем (они имеют четырехбайтовое выравнивание или выровнены по четырем байтам ).

Наиболее ограничительным типом они являются тип, который имеет наиболее ограничительные требования в этой области. Так, если, например, long double требует восьмибайтового выравнивания на какой-либо машине, и ни один другой тип не требует большего выравнивания, чем тот, то наиболее ограничительный тип на этой машине будет long double .

Для malloc(3) имеет смысл возвращать адреса, которые удовлетворяют требованиям выравнивания самого ограничительного типа, поскольку это означает, что возвращаемая память может использоваться для хранения любого типа. malloc() не знает, как будет использоваться память, поэтому она не может адаптироваться.

Не обязательно, чтобы более крупные типы данных требовали большей согласованности, хотя требования к выравниванию, как правило, возрастают с увеличением размера.

(Для некоторых типов данных может потребоваться еще большее выравнивание, чем malloc() . Например, многие инструкции SSH для x86 используют векторы данных, которые выровнены по 16 байтам, в то время как malloc() в glibc гарантирует только восьмибайтовое выравнивание. posix_memalign(3) можно использовать для динамического выделения памяти с еще большими требованиями к выравниванию в системах POSIX (* nix).)

Наиболее ограничивающий тип определяется max_align_t , который определен в stddef.h . Согласно стандарту:

Фундаментальное выравнивание представлено выравниванием, которое меньше или равно наибольшему выравниванию, поддерживаемому реализацией во всех контекстах, которое равно _Alignof (max_align_t) .

Таким образом, max_align_t имеет выравнивание, которое по меньшей мере такое же, как и для каждого типа скаляра, и в большинстве реализаций его выравнивание будет равно наибольшему скалярному типу, но это равенство не требуется стандарту.

Стандарт далее требует (акцент мой):

Порядок и смежность хранилища, выделенные последовательными вызовами aligned_alloc , calloc , malloc и realloc не определены. Указатель возвращается, если выделение успешно выполняется соответствующим образом, чтобы его можно было назначить указателю на любой тип объекта с фундаментальным требованием к выравниванию, а затем использовать для доступа к такому объекту или массиву таких объектов в выделенном пространстве (до тех пор, пока пространство явно освобождено).

Таким образом, любой указатель, возвращаемый функциями распределения, выравнивается по крайней мере так же строго, как выравнивание max_align_t .

Я думаю, что цитата означает наиболее ограничительное выравнивание типов. Например, char является наименее рестриктивным, если следовать этой логике. Объект типа char не налагает ограничение на его выравнивание, тогда как, например, тип int имеет требование выравнивания, обычно равное 4 байтам. Таким образом, int является более ограничительным типом, чем char.