Подтвердить что ты не робот

Как sizeof знает размер массива операндов?

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

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


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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

Цитата из wiki:

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

Ответ 9

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

Ответ 10

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");
}

Ответ 11

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

char * array;
int size;
//Get size somehow.
array = malloc(size*(sizeof(char)));

//теперь во время компиляции компилятор точно знает размер char. так как он должен выровнять их по памяти. На данный момент OS знает, сколько размера он должен выделить.

Маски переменной длины, с другой стороны, создаются на Stack. Но любая память, выделенная malloc, будет создана в куче.

Ответ 12

Размер всегда оценивается во время компиляции. В многопроходном компиляторе при генерации таблицы символов компилятор должен определить размер каждого объявленного символа для продолжения генерации промежуточного кода. Таким образом, для всех sizeof ссылок в коде вместо точного значения. На этапе формирования промежуточного кода все операторы, операторы преобразуются в правый промежуточный код (ASM/другой формат). Наконец, этап генерации кода m/c преобразует его в машинный код.

Некоторые обсуждения, рассмотренные выше w.r.t, динамические распределения, относящиеся к sizeof, вообще не относятся к контексту. Любая ссылка на размер (* p), где p является указателем любого типа данных, компилятор просто обнаруживает тип данных * p и заменяет его размер, а не переходит к проверке заголовка MCB выделенного блока, чтобы увидеть, что является выделенным размер памяти. Это не во время выполнения. Например, double * p; sizeof (* p) все еще можно сделать без выделения памяти для указателя p. Как это возможно?