Почему размеры данных изменяются по мере изменения операционной системы?

Этот вопрос был задан мне в интервью, что размер char составляет 2 байта в некоторой операционной системе, но в некоторой операционной системе это 4 байта или разный.

Почему это так?

Почему он отличается от других фундаментальных типов, таких как int ?

Вероятно, это был спорный вопрос. sizeof(char) всегда 1.

Если размер отличается, вероятно, это связано с несоответствующим компилятором, и в этом случае вопрос должен быть о компиляторе, а не о языке C или C ++.

5.3.3. Размер [expr.sizeof]

1 Оператор sizeof дает количество байтов в представлении объекта его операнда . Операнд – это либо выражение, которое не оценивается, либо идентификатор типа в скобках. Оператор sizeof не применяется к выражению, которое имеет функцию или неполный тип, или к типу enums до того, как все его перечисляющие объявлены, или к имени в скобках таких типов или к значению l, которое обозначает бит-поле. sizeof(char) , sizeof(signed char) и sizeof(unsigned char) равны 1. Результат sizeof, примененный к любому другому фундаментальному типу (3.9.1), определяется реализацией. (акцент мой)

Размер других типов, кроме указанных, определяется реализацией, и они различаются по разным причинам. int имеет более высокий диапазон, если он представлен в 64 битах вместо 32, но он также более эффективен как 32 бита в 32-битной архитектуре.

Физические размеры (по количеству бит) типов обычно продиктованы целевым оборудованием.

Например, некоторые процессоры могут получить доступ к памяти только в единицах не менее 16 бит. Для лучшей производительности, char может быть затем определено 16-разрядное целое число. Если вы хотите использовать 8-разрядные символы на этом CPU, компилятор должен генерировать дополнительный код для упаковки и распаковки 8-битных значений в и из 16-разрядных ячеек памяти. Этот дополнительный код упаковки / распаковки сделает ваш код больше и медленнее.

И это еще не конец. Если вы разделяете 16-разрядные ячейки памяти на 8-битные символы, вы фактически вводите дополнительный бит в адресах / указателях. Если нормальные адреса 16-бит в CPU, где вы придерживаетесь этого дополнительного, 17-го бита? Существует два варианта:

  • сделайте указатели большими (32-битные, из которых 15 не используются), а также потеряйте память и уменьшите скорость
  • уменьшить диапазон адресного адресного пространства наполовину, потратить впустую память и потерять скорость

Последний вариант иногда может быть практичным. Например, если все адресное пространство разделено пополам, одно из которых используется kernelм, а другое – пользовательскими приложениями, то указатели приложений никогда не будут использовать один бит в своих адресах. Вы можете использовать этот бит для выбора 8-битного байта в 16-разрядной ячейке памяти.

C был разработан для работы на как можно большем количестве различных процессоров. Вот почему физические размеры char , short , int , long , long long , void* , void(*)() , float , double , long double , wchar_t и т. Д. Могут различаться.

Теперь, когда мы говорим о разных физических размерах в разных компиляторах, производящих код для одного и того же CPU, это становится скорее произвольным выбором. Однако, возможно, это не так произвольно, как может показаться. Например, многие компиляторы для Windows определяют int = long = 32 бит. Они делают это, чтобы избежать путаницы программиста при использовании Windows API, которые ожидают INT = LONG = 32 бит. Определение int и long поскольку что-то еще будет способствовать ошибкам из-за потери внимания программиста. Итак, в этом случае компиляторы должны последовать этому примеру.

И, наконец, стандарт C (и C ++) работает с chars и bytes . Они – одна и та же концепция по размеру. Но байты C не являются вашими типичными 8-битными байтами, они могут быть юридически более крупными, чем объяснялось ранее. Чтобы избежать путаницы, вы можете использовать термин octet , имя которого означает число 8. В этой цепочке используется несколько протоколов.