Как sizeof знает размер массива операндов? - PullRequest
30 голосов
/ 27 августа 2010

Это может быть глупым вопросом, но как оператор sizeof узнает размер операнда массива, если вы не передаете количество элементов в массиве. Я знаю, что он не возвращает общее количество элементов в массиве, но размер в байтах, но чтобы понять это, ему все равно нужно знать, когда заканчивается массив. Просто любопытно, как это работает.

Ответы [ 12 ]

43 голосов
/ 27 августа 2010

sizeof интерпретируется во время компиляции, и компилятор знает, как был объявлен массив (и, следовательно, сколько места он занимает). Вызов sizeof для динамически размещаемого массива, скорее всего, не будет делать то, что вы хотите, потому что (как вы упоминаете) конечная точка массива не указана.

22 голосов
/ 27 августа 2010

Проблема, лежащая в основе вашей проблемы, заключается в том, что вы путаете массивы и указатели, как это делают многие.Однако массивы не являются указателями .double da[10] - это массив из десяти double, а не double*, и это, безусловно, известно компилятору, когда вы просите его оценить sizeof(da).Вы не удивитесь, что компилятор знает sizeof(double)?

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

14 голосов
/ 27 августа 2010

За исключением одного случая, sizeof делает это во время компиляции. Во время компиляции компилятор отслеживает тип объекта full [Edit: хорошо, все, что он знает о типе объекта, так или иначе - если тип не завершен, так что t включает размер, попытка использовать sizeof потерпит неудачу], и sizeof в основном просто «экспортирует» одну часть этой информации из компилятора в компилируемый код, поэтому она становится по существу постоянной в результирующем коде.

Исключение составляют случаи, когда sizeof применяется к массиву переменной длины (VLA) 1 . При применении к VLA sizeof оценивает его операнд (что не делает иначе) и выдает фактический размер VLA. В этом случае результат не является константой.


1. VLA официально стали частью C в C99, но некоторые компиляторы поддерживали их до этого. Хотя это официально не является частью C ++, некоторые компиляторы (например, g ++) также включают VLA как расширение C ++.

10 голосов
/ 27 августа 2010

Компилятор знает размер каждого типа в вашем приложении, и sizeof просто запрашивает компилятор для создания этого значения для вас.

9 голосов
/ 27 августа 2010

Sizeof - оператор времени компиляции; в нем столько же информации, сколько в компиляторе. (И, очевидно, компилятор знает размер массива).

Вот почему при вызове sizeof для указателя вы получите ширину указателя, а не размер массива, на который указывает этот указатель.

5 голосов
/ 27 августа 2010

Sizeof может применяться только к полностью определенным типам.Компилятор либо сможет определить размер во время компиляции (например, если у вас было объявление типа int foo [8];), либо он сможет определить, что ему нужно добавить код для отслеживания размера переменноймассив длины (например, если у вас было объявление типа int foo [n + 3];).

Вопреки другим ответам здесь, обратите внимание, что начиная с C99 sizeof () не обязательно определяется во время компиляции, поскольку массивы могут иметь переменную длину.

3 голосов
/ 27 августа 2010

Если вы используете sizeof в локальной переменной, он знает, сколько элементов вы объявили.Если вы используете sizeof для параметра функции, он не знает;он обрабатывает параметр как указатель на массив, а sizeof дает размер указателя.

2 голосов
/ 27 августа 2010

sizeof - это обычно , вычисляемое во время компиляции.Заметным исключением являются массивы переменной длины C99.

int main(int argc, char **argv)
{
    if (argc > 1)
    {
        int count = atoi(argv[1]);
        int someArray[count];

        printf("The size is %zu bytes\n", sizeof someArray);
    }
    else puts("No");
}
2 голосов
/ 27 августа 2010

Оператор sizeof «знает» размер всех атомарных типов данных, поскольку структуры, объединения и массивы могут быть созданы только путем сборки атомарных типов, поэтому легко определить размер массива любого типа. Он использует базовую арифметику для определения сложных типов (во время компиляции).

2 голосов
/ 27 августа 2010

Цитата из wiki :

Ответственность за реализацию оператора sizeof лежит на конкретном и корректном для данной реализации языка авторе компилятора.Оператор sizeof должен учитывать реализацию базовой схемы выделения памяти для получения размеров различных типов данных.sizeof обычно является оператором времени компиляции, что означает, что во время компиляции sizeof и его операнд заменяются значением результата.Это очевидно в коде на ассемблере, создаваемом компилятором C или C ++.По этой причине sizeof квалифицируется как оператор, хотя его использование иногда выглядит как вызов функции.

...