Нужно ли знать архитектуру машины для написания кода?

Скажем, я программирую на Java или Python или С++ для простой проблемы, может быть, для создания эхо-сервера TCP/UDP или вычисления факториала. Должен ли я беспокоиться о деталях архитектуры, то есть, если это 32 или 64-разрядный?

IMHO, если я не программирую что-то делать с довольно низкоуровневыми материалами, тогда мне не нужно беспокоиться, если его 32 или 64 бит. Где я иду не так? Или я прав?

Ответы

Ответ 1

правильный для большинства условий

Среда выполнения/язык/компилятор будет абстрагировать эти данные, если вы не будете иметь дело с размерами слов или двоичными данными на низком уровне.

Даже байтовый блок абстрагируется сетевым стеке в ядре. Он переведен для вас. При программировании сокетов в C вам иногда приходится иметь дело с порядком байтов для сети при отправке данных... но это не касается различий 32 или 64 бит.

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

Фактически такие вещи, как Java, запускаются на виртуальной машине, что абстрагирует машину еще один шаг!

Знать немного о наборе команд архитектуры и о том, как скомпилирован синтаксис, что может помочь вам понять платформу и написать более чистый, более жесткий код. Я знаю, что я скривился в каком-то старом C-коде после изучения компиляторов!

Ответ 2

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

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

Для работы с пакетами вам нужно понять, как данные хранятся на платформах и как отправка по сети на другую платформу может изменить способ чтения данных (endian-ness).

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

Так что, короче говоря, нет. Вам не нужно знать материал низкого уровня, но он никогда не боится знать.

Ответ 3

Иногда вам приходится беспокоиться.

Вы можете быть удивлены, когда эти низкоуровневые детали внезапно выпрыгнут и укусят вас. Например, Java стандартизованный double должен быть 64 бит. Тем не менее, Linux JVM использует режим "расширенной точности", когда double равен 80 бит до тех пор, пока он находится в регистре CPU. Это означает, что следующий код может выйти из строя:

double x = fun1();
double y = x;

System.out.println(fun2(x));

assert( y == x );

Просто потому, что y вытесняется из регистра в память и усекается от 80 до 64 бит.

Ответ 4

В прошлый раз, когда я смотрел спецификацию языка Java, в нем содержалась нелепая ошибка в разделе о целочисленном боксе.

Integer a = 100;
Integer b = 100;

System.out.println(a == b);

Это гарантирует печать true.

Integer a = 300;
Integer b = 300;

System.out.println(a == b);

Это не гарантируется печать true. Это зависит от времени выполнения. Спектр оставил его полностью открытым. Это потому, что бокс int между -128 и 127 возвращает "интернированные" объекты (аналогично тому, как строковые литералы интернированы), но разработчику среды выполнения языка рекомендуется повышать этот предел, если они того пожелают.

Я лично считаю это безумным решением, и я надеюсь, что они исправили его с тех пор (пишите один раз, бегите куда-нибудь?)

Ответ 5

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

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

Ответ 6

Пока вы делаете все правильно, вам почти не нужно знать большинство языков. На многих вам никогда не нужно знать, поскольку поведение на языке не меняется (например, Java указывает точное поведение во время выполнения).

В С++ и C правильные действия включают в себя не допущение предположений о int. Не ставьте указатели в int, и когда вы делаете что-либо с размерами или адресами памяти, используйте size_t и ptrdiff_t. Не рассчитывайте на размер типов данных: int должен быть не менее 16 бит, почти всегда 32 и может быть 64 на некоторых архитектурах. Не предполагайте, что арифметика с плавающей запятой будет выполняться точно так же на разных машинах (стандарты IEEE имеют некоторую свободу действий в них).

Практически все операционные системы, поддерживающие сетевое взаимодействие, дадут вам какой-то способ справиться с возможными проблемами с энтианностью. Используй их. Используйте языковые средства, такие как isalpha(), чтобы классифицировать символы, а не арифметические операции над символами (что может быть чем-то странным, как EBCDIC). (Конечно, теперь более привычно использовать wchar_t как тип символа и использовать Unicode внутри.)

Ответ 7

Если вы программируете на Python или в Java, интерпретатор и виртуальная машина соответственно абстрагируют этот слой архитектуры. Тогда вам не нужно беспокоиться, если он работает на архитектуре с 32 или 64 битами.

То же самое нельзя сказать о С++, в котором вам придется иногда спрашивать себя, если вы работаете на 32- или 64-битной машине

Ответ 8

Вам нужно будет заботиться о "endian-ness", только если вы отправляете и получаете необработанные C-структуры по проводу, например

ret = send(socket, &myStruct, sizeof(myStruct));

Однако это не рекомендуется.

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

Ответ 9

В С++ вы должны быть очень осторожны, если хотите написать код, который работает равномерно на 32 или 64 бита. Многие ошибочно полагают, что int может хранить указатель, например.

Ответ 10

С java и .net вам действительно не нужно беспокоиться об этом, если вы не делаете очень низкоуровневые вещи, такие как биты. Если вы используете c, С++, fortran, вы можете пройти, но я бы рекомендовал использовать такие вещи, как "stdint.h", где вы используете определенные объявления, такие как uint64_t и uint32_t, чтобы быть явным. Кроме того, вам нужно будет строить с особенностями библиотеки в зависимости от того, как вы связываете, например, 64-битная система может использовать gcc в режиме компиляции по умолчанию 64 бит.

Ответ 11

32-разрядная машина позволит вам иметь не более 4 ГБ адресной виртуальной памяти. (На практике это даже меньше, чем обычно, 2 ГБ или 3 ГБ в зависимости от ОС и различных вариантов компоновщика.) На 64-битной машине у вас может быть ОГРОМНОЕ виртуальное адресное пространство (в любом практическом смысле, ограниченное только диском ) и довольно проклятая большая оперативная память.

Итак, если вы ожидаете набора данных на 6 Гбайт для некоторых вычислений (скажем, что-то, что требует некогерентного доступа и не может быть просто потоковым потоком), на 64-битной архитектуре вы можете просто прочитать ее в ОЗУ и сделать ваши вещи, тогда как в 32-битной архитектуре вам необходим принципиально другой подход к ней, поскольку у вас просто нет возможности сохранить весь резидентный набор данных.