toni_1 Ответов: 2

Разные результаты с размером


Привет,
я смущен результатом команды sizeof.
В основной функции результат равен 16, а в функции printArr-4.
Есть идеи?
Тнх

Что я уже пробовал:

void printArr(int arr[]) {

	int i = 0;
	int max = sizeof(arr);
	//int max = (sizeof(arr) / sizeof(arr[0])

	std::cout << "size of arr in function = " << sizeof(arr) << std::endl;

	do {
		std::cout << arr[i] << std::endl;
		i++;
	} while (i < max);

}

int main() {

	int arr[] = { 1,2,3,4 };

	std::cout << "size of arr in main =" << sizeof(arr) << std::endl; // SIZE = 16

	printArr(arr);

	system("pause");
	return 0;
}

2 Ответов

Рейтинг:
17

OriginalGriff

Это потому что они измеряют разные вещи: arr в main объявляется как массив из четырех целых чисел: поскольку целое число в вашей системе составляет 32 бита, размер всего массива в 4 раза больше размера целого числа == 4 * 4 == 16

В printArr он объявлен как int arr[], что означает, что у него нет информации о размере, и декларация приравнивается к int *arr - на самом деле эта декларация будет работать точно так же, и даст вам точно такие же результаты. Помните, что все параметры в C и C++ по умолчанию передаются по значению, поэтому создается копия значения и передается параметру функции, а не передаваемому "реальному объекту". С массивом вы передаете не копию массива, а копию указателя на первый элемент (в противном случае вы не смогли бы передать какие-либо изменения данных массива обратно вызывающей функции).

Так что в printArr, arr не имеет информации о размере и фактически является указателем на целое число (поэтому система не пытается скопировать весь массив и передать вашей функции копию, которую она передает указателю на первый элемент)

А в вашей системе любой указатель равен 32 битам, поэтому вы получаете результат "4", так как все указатели помещаются в 4 байта.
В моей системе я получаю "16" и "8", потому что все мои указатели имеют ширину 64 бита, а для хранения требуется 8 байт.


toni_1

Большое спасибо!! Эта информация мне очень помогает !

OriginalGriff

Всегда пожалуйста!

Рейтинг:
1

John R. Shaw

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

Я дам вам 3 варианта:
1) func(int arg[], int argn n);
2) func(int *arg, int argn n);
3) func(int arg[10]);

Только число 2 имеет смысл, а число 1-это в основном одно и то же. Номер 3 законен, но он ограничивает то, что может быть передано и исключено.

Я ненавижу слово "никогда", но я рекомендую вам никогда не использовать число 3, Если у вас нет очень явной причины для этого (аппаратные требования - очень низкий уровень).


0x01AA

"... передать массив по значению ..." в c++, как вы это делаете? :-)

John R. Shaw

Технически, это был бы номер 3. Это то, что "toni_1" думал, что он/она делает. Копинг по значению означает, что копия передается в стек, что и делает номер 3. То, что делал 'toni_1', сводилось к передаче указателя на исходный массив, что означает, что любое изменение массива в функции изменит оригинал. Номер 3 изменит только копию. Вот почему нам нужно указать постоянные переменные в наших аргументах (я говорю вам, где находятся данные, но вы не можете их изменить).

:) Рубикс - лучшее время 2.54 минуты (сейчас, понятия не имею).

0x01AA

:большой палец вверх: :)