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

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

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

Наиболее ограничительный тип определяется max_align_t, который определен в stddef.h. В соответствии со стандартом:

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

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

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

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

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

Ответ 3

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