Иллюстрированный самоучитель по практике программирования

Язык

Арифметический или логический сдвиг.
Сдвиг вправо знаковых величин с помощью оператора " может быть арифметическим (при сдвиге распространяется копия знакового бита) или логическим (при сдвиге освободившиеся биты заполняются нулями). И здесь Java, наученная горьким опытом С и C++, резервирует " для арифметического сдвига вправо и предоставляет отдельный оператор >>> для логического сдвига вправо.

Порядок байтов.
Порядок байтов внутри short, int и long не определен; байт с младшим адресом может быть как наиболее значимым, так и наименее значимым. Этот вопрос зависит от аппаратуры, и мы подробно обсудим его несколько ниже в этой главе.

Выравнивание членов структуры или класса.
Расположение элементов внутри структур, классов и объединений (union) не определено, утверждается лишь, что члены располагаются в порядке объявления. Например, в структуре:

Иллюстрированный самоучитель по практике программирования › Переносимость › Язык

Адрес 1 может находиться на расстоянии 2, 4 или 8 байтов от начала структуры. Некоторые (немногие) машины позволяют целым храниться на нечетных границах, но большинство требует, чтобы п-байтовые элементарные типы данных хранились на и-байтовых границах, чтобы, например, double, которые имеют, как правило, длину в 8 байтов, хранились по адресам, кратным 8. В дополнение к этому создатели компиляторов могут вносить и свои ограничения – такие как принудительное выравнивание для повышения производительности.

Никогда не рассчитывайте на то, что элементы структуры занимают смежные области памяти. Ограничения на выравнивание вызывают появление "дыр" в структурах – так, struct X всегда будет содержать по крайней мере один байт неиспользуемого пространства. Из-за этих дыр размер структуры может быть больше, чем сумма размеров ее членов, причем этот размер может быть разным на разных машинах. Если вы хотите зарезервировать память под структуру, всегда запрашивайте sizeof (struct X) байтов, но не sizeof (char) + sizeof(int).

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

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

Иллюстрированный самоучитель по практике программирования › Переносимость › Язык

Не сравнивайте char с EOF. Всегда используйте sizeof для вычисления размера типов и объектов. Никогда не сдвигайте вправо знаковые значения. Убедитесь, что тип данных достаточно велик для диапазона значений, которые вы собираетесь в нем хранить.

Попробуйте несколько компиляторов.
Иногда вам может показаться, что вы решили все проблемы с переносимостью, однако компиляторы в состоянии увидеть проблемы, который не вы заметили, и вообще, разные компиляторы воспринимают вашу программу по-разному, и этим; можно воспользоваться. Включите все предупреждения компилятора. Попробуйте использовать разные компиляторы на одной машине и на разных машинах. Попытайтесь компилировать вашу С-программу на компиляторе C++.

Поскольку язык, воспринимаемый различными компиляторами, может несколько отличаться от стандарта, тот факт, что ваша программа компилируется одним компилятором, не дает гарантии даже того, что она корректна синтаксически. А вот если несколько компиляторов принимают ваш код, значит, все не так плохо. Мы компилировали каждую программу, приведенную в книге, на трех компиляторах С для трех различных операционных систем (Unix, Plan 9, Windows) и на паре компиляторов C++. При таком подходе были найдены десятки ошибок переносимости – никакое самое пристальное изучение программ чeлoвeкoм не смогло бы найти их все. Исправлялись же все ошибки тривиально.

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

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.