Как sizeof рассчитывает размер структур

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

.equals() тесты для равенства значений (независимо от того, являются ли они логически «равными»).

Objects.equals () проверяет наличие null перед вызовом .equals(), поэтому вам не нужно (доступно с JDK7, также доступным в Guava ).

String.contentEquals () сравнивает содержимое String с содержимым любого CharSequence (доступно с Java 1.5).

Следовательно, если вы хотите проверить, имеет ли две строки одно и то же значение, вы, вероятно, захотите использовать Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Вы почти всегда хотите использовать Objects.equals(). В редкой ситуации, когда вы знаете, что имеете дело с интернированными строками, вы можете использовать ==.

Из JLS 3.10. 5. Строковые литералы :

Кроме того, строковый литерал всегда ссылается на тот же экземпляр класса String. Это связано с тем, что строковые литералы, или, в более общем смысле, строки, которые являются значениями константных выражений ( §15.28 ), «интернированы», чтобы обмениваться уникальными экземплярами, используя метод String.intern.

blockquote>

. Подобные примеры также можно найти в JLS 3.10.5-1 .

13
задан Gearoid Murphy 17 April 2010 в 19:30
поделиться

5 ответов

Это потому, что int составляет 4 байта и должен быть выровнен по 4-байтовой границе. Это означает, что ЛЮБАЯ структура , содержащая int , также должна быть выровнена как минимум по 4 байтам.

С другой стороны, short составляет 2 байта и требует выравнивания только по 2-байтовой границе. Если структура , содержащая short s, не содержит ничего, что требует большего выравнивания, структура также будет выровнена по 2 байтам.

22
ответ дан 1 December 2019 в 17:47
поделиться

Эта ссылка должна помочь: http://en.wikipedia.org/wiki/Data_structure_alignment

В ThreeShorts все элементы выровнены по двум байтам.

1
ответ дан 1 December 2019 в 17:47
поделиться

Это действительно меня озадачивает, почему не применяется выравнивание для t

Какое выравнивание вы хотите, чтобы оно было?

Шорты можно выровнять на 2-байтовых границах без вредных последствий (при условии, что здесь повсюду распространены компиляторы x86 ..). Поэтому, если вы создаете массив из struct ThreeeShorts , эта структура размером 6 вполне подойдет, так как любые элементы в таком массиве будут начинаться с 2-байтовой границы.

Ваша struct IntAndChar содержит int, ints требует 4-байтового выравнивания, поэтому, если вы создаете массив из struct IntAndChar , размер должен быть 8, чтобы следующий элемент был выровнен на 4-байтовой границе.

Если бы мы не рассматривали массивы, это не имело бы большого значения, если бы длина struct IntAndChar составляла 5 байтов, компилятор просто выделял бы его, начиная с 4-байтовой границы, когда вы создаете один в стеке. или используйте его как составной член в другой структуре.

Вы всегда можете получить количество элементов в массиве, выполнив sizeof (arrayofT) / sizeof (T), и элементы массива гарантированно будут храниться рядом друг с другом, так что n'-й элемент может быть извлечен с помощью шага N * sizeof (arrayelementtype) байтов с самого начала, и это основная причина, по которой вы увидите, что структуры заполняются в конце.

15
ответ дан 1 December 2019 в 17:47
поделиться

Не знаю, откуда вы взяли, что char или int вычисляются как «8 байт». Нет, каждый тип вычисляется в соответствии со своим размером: char как 1, int как 4 на 32-битной платформе (не 8, а 4). Требования к выравниванию для каждого типа обычно такие же, как и его размер (хотя это не обязательно).

По этой причине, когда структура содержит элементы того же типа , общий размер этой структуры обычно будет точной суммой размеров ее элементов: структура из 3 char s будет иметь размер 3, а структура из двух int s будет иметь размер 8.

Очевидно, type short на вашей платформе имеет размер 2, поэтому, как и следовало ожидать , структура из 3 шорт имеет размер 6, что вы и наблюдаете.

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

Например, структура, которая выглядит следующим образом

struct S {
  char c;
  int i;
};

, скорее всего, займет 8 байтов на вашей платформе из-за необходимости в 3 байта заполнения после члена char .Обратите внимание, что char считается как 1, int - как 4, а дополнительные 3 байта заполнения между ними составляют 8.

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

struct S1 {
  char c1;
  int i;
  char c2;
};

на вашей платформе, вероятно, будет иметь размер 12, а эта

struct S2 {
  int i;
  char c1;
  char c2;
};

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

6
ответ дан 1 December 2019 в 17:47
поделиться

Это полностью зависит от реализации, но, предположительно, если ваша система может получить доступ к любому из трех коротких в struct, не беспокоясь о выравнивании, она может получить доступ к любому short и, следовательно, к любому члену данных в массиве ThreeShorts , не беспокоясь о выравнивании. Следовательно, нет необходимости более строго выравнивать конструкции.

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

размер массива T [n] точно определяется как sizeof (T) * n .

2
ответ дан 1 December 2019 в 17:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: