Как распознается массив C ++? - PullRequest
0 голосов
/ 19 февраля 2020

Когда вы передаете массив в C ++, он передается как указатель. Поэтому мы должны явно передать размер этого массива.

// This will not work.
int GetSize(int* arr){
  return sizeof(arr)/size(int);
}

Но если мы не используем функцию, чтобы получить ее размер, и используем "sizeof" в той же функции, где был инициализирован массив, теперь мы получаем правильный результат.

int main(){
  int arr[5];
  int size = sizeof(arr)/sizeof(int);
  cout << size << endl;
}

Так что мне достаточно взглянуть на массив как на класс с указателем, его размером и типом элементов в нем?

Теперь, когда Я думаю об этом, я не уверен, как C ++ знает размер массива в последнем коде, если он обрабатывается так же, как указатель.

Ответы [ 4 ]

2 голосов
/ 19 февраля 2020

Так мне ли достаточно рассматривать массив как класс с указателем, его размером и типом элементов в нем?

Нет, потому что это не так. Массив C -стилей - это просто кусок непрерывной памяти, содержащей элементы данного типа, не более, не менее.

Теперь, когда я думаю об этом, я не уверен, как C ++ знает размер массива в последнем коде, если он обрабатывается так же, как указатель.

Это не то, как обрабатываются массивы.

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

Во втором примере фактический массив находится в области видимости, где используется sizeof(). Компилятор знает объявление массива, поэтому sizeof(arr) может знать фактический размер байта массива.

Если вы действительно хотите знать размер переданного массива в функции и не хотите передать размер явно в качестве параметра, а затем передать массив по ссылке вместо указателя , чтобы размер массива не терялся:

template<size_t N>
int GetSize(int (&arr)[N]){
  return N;
}
0 голосов
/ 19 февраля 2020
  1. Почему sizeof(), когда в том же объеме? - Это потому, что компилятор видит, что вы объявили int arr[5], он получает размер 5 во время компиляции. sizeof() вычисляется во время компиляции.
  2. Почему это не работает, когда массив передается как указатель? - Это потому, что массив превращается в указатель здесь. Следовательно, он теряет информацию о размере. Infact, sizeof(arr) здесь даст вам размер указателя в вашей системе - 8 байтов для 64-битной машины, 4 байта для 32-битной машины.
0 голосов
/ 19 февраля 2020

В первом случае, как я правильно понимаю, вы берете размер типа int *, который является указателем на int, и в большинстве случаев он будет иметь размер 4 байта (в зависимости от архитектуры и, возможно, других факторов).

Во втором случае компилятор также имеет всю информацию, необходимую для вычисления sizeof (arr), поскольку явно задано 5 элементов int, как определено в int arr [5]; и в результате в большинстве случаев будет равен 4 байта * 5 элементов, 20 байтов

0 голосов
/ 19 февраля 2020

Объявление

int *arr; // arr = ptr to int

отличается от объявления

int arr[5];  // arr = base ptr to array of 5 ints

Обратите внимание, что arr разрешает адрес (ptr) в каждом случае, но во втором случае Компилятор может решить, что arr является базовым ptr для массива из 5 int. Ситуация становится немного хитрее, если второе объявление предназначено для параметра функции:

void foo(int arr[5]) { ... }

, тогда это действительно ничем не отличается от

void foo(int *arr) { ... }
void foo(int arr[]) { ... }

, т.е. передается только ptr и sizeof(arr) вернет количество байтов в ptr.

...