Почему разные типы символов занимают одинаковую длину? - PullRequest
0 голосов
/ 26 апреля 2018

Я скомпилировал приведенный ниже код с помощью cygwin GCC на компьютере x64:

gcc main.c -o main

(main.c)

long long mango = 13; // I also tried `char`, `short`, `int`
long melon = 2001;

void main()
{

}

Затем я сбрасываю значения символов с помощью nm:

./main:0000000100402010 D mango
./main:0000000100402018 D melon

Как я понимаю, значение символа просто означает его адрес. Таким образом, адрес для mango равен 100402010. И melon имеет адрес 100402018. Так что mango должен занимать 8 байтов.

Я пробовал другие типы для mango, такие как char, int, short. Он всегда занят 8 байтами.

Почему размер не меняется?

ADD 1

Спасибо за комментарий.

Я только что попробовал ниже код:

typedef struct{
    char a1;
    char a2;
    char a3;
    char a4;
    char a5;
} MyStruct;

MyStruct MyObj1={1,2,3,4,5};

MyStruct MyObj2={1,2,3,4,5};

long long mango = 13;
long melon = 2001;

void main()
{

}

И на этот раз nm показывает мне это:

./main:0000000100402020 D mango
./main:0000000100402028 D melon
./main:0000000100402010 D MyObj1
./main:0000000100402015 D MyObj2

MyObj1 и MyObj2 разделены 5 байтами. Так что компилятор действительно должен решить заполнение.

1 Ответ

0 голосов
/ 26 апреля 2018

Из бинарных утилит GNU nm: страница nm :

Значение символа в радиусе, выбранном опциями (см. Ниже), или шестнадцатеричный по умолчанию. Тип символа. По крайней мере, следующие типы используются; другие также зависят от формата объектного файла. Если строчный символ обычно местный; если заглавными, символ глобальный (внешний). Однако есть несколько строчных символов, которые показано для специальных глобальных символов (u, v и w). В зависимости от настроек pragma и границ выравнивания по умолчанию расстояние между последовательными адресами символов может быть точным значением количества байтов для этого символа type или может включать заполнение , который увеличивает видимый размер символа.

A

    The symbol’s value is absolute, and will not be changed by further linking.
B
...

IMO использование слова value на языке nm является неудачным, так как в этом контексте value используется для обозначения адреса символа. адрес символа (значения) не изменится. Но на обычном языке C значение символа действительно меняется, например:

int i = 0; // the address for symbol i will remain constant
i = 10;    // but the value of the symbol i can change. 

Что касается размера адресов, адрес любого символа для 64-битной сборки всегда будет иметь размер 8 байтов, в то время как адрес любого символа в 32-битной сборке будет иметь размер 4 байта. Эти размеры не изменяются, и на них не влияет назначение значения назначенному им символу.

Что касается расстояния в пространстве памяти, которое происходит между различными символами, на это расстояние влияет как type символа, так и то, как оно выровнено вдоль границ реализации, и , как вы заметили, компилятор: «Так что компилятор действительно должен решить заполнение.» В зависимости от pragma настроек и границ выравнивания по умолчанию, заполнение может привести к тому, что адреса для последовательных символов будут находиться на большем расстоянии, чем то, что вызвано только комбинированными sizeof значениями type или types, которые определяют конкретный символ. (очень распространенное явление для символов типа char и struct).

...