2012-09-06 5 views
1

Сегодня я узнал, что если вы объявите переменную char (которая составляет 1 байт), ассемблер фактически использует 4 байта в памяти, так что границы лежат на кратных размеру слова.Ассемблеры и выравнивание слов

Если переменная char использует 4 байта в любом случае, какова точка объявления ее как символа? Почему бы не объявить его как int? Разве они не используют одинаковый объем памяти?

+1

Вы пробовали массив символов? – Nemo

+3

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

ответ

4

Когда вы пишете на языке ассемблера и объявить пространство для персонажа, ассемблер выделяет пространство для одного символа и не более. (Я пишу об общих сборщиках.) Если вы хотите выровнять объекты на языке ассемблера, для этой цели вы должны включить директивы ассемблера.

Когда вы пишете на C, а компилятор переводит его на сборку и/или машинный код, пространство для символа может быть дополнено. Обычно это не делается из-за преимуществ выравнивания для объектов символов, а потому, что у вас есть несколько вещей, объявленных в вашей программе. Например, рассмотрим, что происходит, когда вы объявляете:

char a; 
char b; 
int i; 
char c; 
double d; 

Наивный компилятор может сделать это:

  • Выделяют один байт для a в начале соответствующей памяти, что случается, выравниваются по кратное, скажем, 16 байт.
  • Выделите следующий байт для b.
  • Затем он хочет разместить int i, которому требуется четыре байта. На этой машине объекты int должны быть выровнены по краям четырех байтов, или программа, пытающаяся получить к ним доступ, выйдет из строя. Таким образом, компилятор пропускает два байта и затем выделяет четыре байта для i.
  • Выделите следующий байт за c.
  • Пропустить семь байтов, а затем выделить восемь байтов для d. Это делает d совпадающим с кратным восьми байтам, что выгодно для этой гипотетической машины.

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

Умнее компилятор сделает это:

  • Сортировать объекты, которые он должен выделить место для в соответствии с их требованиями выравнивания.
  • Сначала укажите наиболее ограничительный объект: отложите восемь байтов для d.
  • Поместите следующий наиболее ограничительный объект: выделите четыре байта для i. Обратите внимание, что i выровнен с кратным четырем байтам, поскольку он соответствует d, который представляет собой восьмибайтовый объект, выровненный с кратным восьми байтов.
  • Поместите наименее ограничительные объекты: Отложите один байт на a, b и c.

Этот тип переупорядочения позволяет избежать потери пространства, и любой достойный компилятор будет использовать его для памяти, которую он может организовать (например, автоматические объекты в стеке или статические объекты в глобальной памяти).

Когда вы объявляете членов внутри структуры, компилятор должен использовать порядок, в котором вы объявляете членов, поэтому он не может выполнить это переупорядочение, чтобы сэкономить место. В этом случае объявление объектов символов и других объектов может потерять пространство.

0

Возможно, нет смысла объявлять одну переменную char.

Там, однако, может быть много причин хотеть char - массив, где int -array действительно не будет делать трюк!

(Попробуйте дополняя структуру данных с Интсами ...)

+0

Если вы используете массив символов, каждый символ использует только 1 байт? –

+1

@badatmath: это действительно само определение 'char'. –

+1

попробуйте и посмотрите. –

3

Q: выделить ли программа четыре байта для каждого «полукокса» вы объявляете?

A: Нет - абсолютно нет;)

Q: Возможно ли, что, если выделить один байт, программа может «подушечка» с дополнительными байтами?

A: Да - абсолютно да.

Проблема «выравнивание». Некоторые компьютерные архитектуры должны получить доступ к значению данных относительно конкретного смещения: 16 бит, 32 бит и т. Д. Другие архитектуры работают лучше, если они всегда получают доступ к байту относительно смещения. Следовательно, «набивка»:

0

Другие по большей части ответили на это. Предполагая, что char - это один байт, объявляет ли символ, что он всегда накладывается на выравнивание? Нет, некоторые компиляторы по умолчанию не работают, и многие из них могут поменять значение по умолчанию, используя какую-то команду. Означает ли это, что вы не должны использовать символ? Это зависит, во-первых, отступ не всегда случается, поэтому несколько потерянных байтов не всегда случаются. Вы программируете на языке высокого уровня, используя компилятор, поэтому, если вы считаете, что у вас есть только 3 потерянных байта в вашем двоичном файле ... подумайте еще раз. В зависимости от архитектуры, использующей символы, могут быть сбережения, например, загрузка сразу же сохраняет три байта или более на некоторых архитектурах. Другие архитектуры просто для выполнения простых операций с дополнительными инструкциями для регистрации необходимы для подписи расширения или клипа большего регистра, чтобы вести себя как регистр размера байта. Если вы находитесь на 32-битном компьютере, и вы используете 8-битный символ, потому что вы только считаете от 1 до 100, вы можете использовать полный размер int, в конечном счете вы, вероятно, ничего не спасаете, используя голец. Теперь, если это 8086-основанный компьютер, работающий с dos, это совсем другая история. Или 8-битный микроконтроллер, тогда вы хотите как можно больше наклониться к 8-битным переменным.

Смежные вопросы