Действительно ли байт является минимально адресуемой единицей? - PullRequest
2 голосов
/ 15 февраля 2020

Раздел 3.6 стандарта C11 определяет «байт» как «адресуемую единицу хранения данных ... для хранения ... символа».

Раздел 1.7 стандарта C ++ 11 определяет «байт» как « основная единица хранения в модели памяти C ++ ... содержит ... символ ".

В обоих определениях не говорится, что" байт "является минимальной адресуемой единицей. Это потому, что стандарты намеренно хотят абстрагироваться от конкретной c машины? Можете ли вы привести реальный пример машины, на которой для компилятора C / C ++ было решено иметь «байт» длиннее / короче минимальной адресуемой единицы?

Ответы [ 5 ]

7 голосов
/ 15 февраля 2020

Байт - это наименьшая адресуемая единица в строго соответствующем коде C. Неважно, будет ли машина, на которой реализация C выполняет программу, поддерживать адресацию меньших единиц; реализация C должна представлять представление, в котором байты являются наименьшей адресуемой единицей в строго соответствующем C коде.

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

2 голосов
/ 15 февраля 2020

Одним примером реальной машины и ее компилятора, где минимальная адресуемая единица меньше байта, является семейство 8051. Один из используемых мной компиляторов - Keil C51.

Минимальная адресуемая единица - бит. Вы можете определить переменную этого типа, вы можете прочитать и записать ее. Однако синтаксис для определения переменной нестандартен. Конечно, C51 необходимо несколько расширений для поддержки всего этого. Кстати, указатели на биты не разрешены.

Например:

unsigned char bdata bitsAdressable;
sbit bitAddressed = bitsAdressable^5;

void f(void) {
    bitAddressed = 1;
}

bit singleBit;

void g(bit value) {
    singleBit = value;
}
1 голос
/ 16 февраля 2020

Я запрограммировал как TMS34010 , так и его последующие графические чипы TMS34020 еще в начале 1990-х годов, и они имели плоское адресное пространство и были бит адресуемыми, то есть адресами, индексированными для каждого бита. Это было очень полезно для компьютерной графики того времени и тогда, когда память была намного более драгоценной.

встроенный C -компилятор действительно не имел прямого доступа к отдельным битам поскольку с (стандартной) языковой точки зрения C байт был наименьшей единицей, как указано в предыдущем посте.

Таким образом, если вы хотите читать / записывать поток битов в C, вам нужно читать / записывать (как минимум) байт за раз и буфер (например, при записи кодера Arithmeti c или Хаффмана).

1 голос
/ 16 февраля 2020

В обоих определениях не говорится, что "байт" является минимальной адресуемой единицей.

Это потому, что им это не нужно. Байтовые типы (char, unsigned char, std::byte и т. Д. c) имеют достаточные ограничения, обеспечивающие соблюдение этого требования.

Размер побайтных типов явно определен для быть точно 1 :

sizeof (char), sizeof (char со знаком) и sizeof (char без знака) равны 1.

Выравнивание побайтово типы - наименьшее возможное выравнивание :

Кроме того, узкие типы символов (6.9.1) должны иметь самое слабое требование выравнивания

Это не Конечно, выравнивание не должно быть равным 1. За исключением ... это так.

Видите, если бы выравнивание было больше 1, это означало бы, что простой байтовый массив не работал бы. Индексирование массива основано на арифметике указателя c, а арифметика указателя c определяет следующий адрес на основе sizeof(T). Но если alignof(T) больше sizeof(T), то второй элемент в любом массиве T будет смещен. Это недопустимо.

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

В целом это означает, что каждый указатель к объекту имеет выравнивание, по крайней мере, такое же ограничительное, как и для байтового типа. Таким образом, указатель объекта не может быть смещен относительно выравнивания побайтовых типов. Поэтому все действительные указатели, отличные от NULL (указатели на активный объект или указатель конца-в-конце) должны быть как минимум выровнены настолько, чтобы указывать на char.

Аналогично, разница между двумя указатели определены в C ++ как разница между индексами массивов элементов, на которые указывают эти указатели (арифметика указателей c в C ++ требует, чтобы два указателя указывали на один и тот же массив). Арифметическое указателя аддитива c соответствует указанному ранее на основе sizeof типа, на который указывает тип.

Учитывая все эти факты, даже если в реализации есть указатели, адреса которых могут адресовать значения, меньшие char , функционально невозможно для абстрактной модели C ++ сгенерировать указатель и при этом иметь счетчик указателей как действительный (указывающий на объект / функцию, конец массива или значение NULL) , Вы можете создать такое значение указателя с помощью приведения из целого числа. Но вы бы создали недопустимое значение указателя.

Таким образом, хотя технически на машине могут быть меньшие адреса, вы никогда не сможете использовать их в действительной, правильно сформированной программе C ++.

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

0 голосов
/ 16 февраля 2020

(Спасибо всем, кто прокомментировал и ответил, каждое слово помогает)

Модель памяти языка программирования и модель памяти целевой машины - разные вещи.

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

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

  • длиннее: HP Saturn - 4-битная единица против 8- битовый байт g cc (спасибо Нейт).
  • короче: IBM 360 - 36-битный блок против 6-битного байта (спасибо Antti)
  • длиннее: Intel 8051 - 1-разрядный модуль против 8-разрядного байта (спасибо Busybee)
  • более длинный: Ti TMS34010 - 1-разрядный модуль против 8 байт (спасибо Wcochran)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...