Указатель на дилемму массива

У меня довольно простой вопрос о массивах и указатель на массивы.
рассмотрим этот фрагмент кода ..

int (*ptr)[3];               //A pointer to an array of 3 ints
int arr1[3] = {2,4,6,};
ptr = &arr1;                //ptr now points to arr1

//3 different ways to express  the same address
cout << &arr1 << "\t" << arr1 << "\t" << &arr1[0] << endl;

Сейчас если:

&arr1 == arr1 == &arr1[0]..

почему этот код неверен:

ptr = arr1;

или же

ptr = &arr1[0];

Это сводит меня с ума … поэтому, пожалуйста, любые объяснения будут оценены. Также, пожалуйста, не говорите, что это не домашнее задание, а то, что я пытаюсь понять.

2

Решение

В

ptr = arr1;

arr1 превращается в int*Таким образом, вы пытаетесь назначить из несовместимого типа указателя. &arr1[0] это прямо int*без преобразования, так что опять несовместимо.

&arr1 == arr1 == &arr1[0]

неверно, поскольку сущности имеют разные типы. Они указывают только на один и тот же адрес, поэтому при печати они дают одинаковый результат.

5

Другие решения

В большинстве случаев выражение с типом массива неявно преобразуется в указатель на первый элемент такого массива, как объяснено в 6.3.2.1p3:

За исключением случаев, когда это операнд sizeof оператор, _Alignof оператор или
унарный & оператор, или строковый литерал, используемый для инициализации массива, выражение, которое имеет
тип массив типа преобразуется в выражение с типом указатель на тип это указывает
к начальному элементу объекта массива и не является lvalue.

Таким образом, правая часть вашего задания

ptr = arr1;

неявно преобразуется в несовместимый тип указателя (int* против int (*)[3]), и не может быть сохранен в переменной указателя без приведения.

Это не является исключением из любого правила, так как вам нужно использовать & Оператор с другими типами тоже:

T val, *ptr;
ptr = &val;
3

Программа ниже поможет вам лучше понять разницу между
pointer_to_first_member_of_array, pointer_to_1D_array, pointer_to_2D_array.
Пожалуйста, внимательно посмотрите на программу, запустите ее и посмотрите вывод.

#include<stdio.h>

int priv_element = 88;

int array[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int next_element = 99;

main (int argc, char *argv[])
{

int *ptr_to_first_element = &array[0][0];

int (*ptr_to_1d_arry)[5] = &array[0];

int (*ptr_to_2d_arry)[2][5] = &array;

printf ("Print first num of first array of 2-Dim array: %d\n",
*ptr_to_first_element);

ptr_to_first_element += 5;

printf ("Print first num of second array of 2-Dim array: %d\n",
*ptr_to_first_element);

printf ("Print first num of first array of 2-Dim array: %d\n",
(*ptr_to_1d_arry)[0]);

ptr_to_1d_arry++;

printf ("Print first num of second array of 2-Dim array: %d\n",
(*ptr_to_1d_arry)[0]);

printf ("Print first num of first array of 2-Dim array: %d\n",
(*ptr_to_2d_arry)[0][0]);

ptr_to_2d_arry++;

printf
("Now you increased to point end of 2d-array space. So next to it is next_element on data-seg: %d\n",
(*ptr_to_2d_arry)[0][0]);

}
1

Когда вы напечатали различные выражения, это показало вам, что их ценности мы одинаковы. Тем не менее, они не имеют одинаковые типы.

C и C ++ включают в себя функции типов, чтобы уменьшить количество человеческих ошибок и облегчить написание сложного кода. Предположим, у вас был адрес в каком-то указателе p, а C / C ++ позволял вам делать либо:

float *f = p;

или же:

int *i = p;

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

Точно так же ваш ptr это указатель на массив из трех int, Сначала это может показаться вашим arr1 также массив из трех int, так что вы должны иметь возможность назначить ptr = arr1;, Это неправильно, потому что ptr это просто указатель, но arr1 является целым объектом массива. Вы не можете поместить весь массив в указатель; вам нужно поместить указатель на массив в указатель. Чтобы получить указатель на массив, вы используете & оператор: ptr = &arr1;,

Другая вещь, которая сбивает с толку, заключается в том, что C / C ++ включает в себя автоматический ярлык: он преобразует массив в указатель на первый элемент массива. когда arr1 появляется в большинстве контекстов, она автоматически изменяется на &arr1[0], Для этого нет огромной философской причины; это просто удобство для способов, которыми мы часто используем массивы. Так ptr = arr1; будет эквивалентно ptr = &arr1[0];, что тоже не допускается. В этой форме вы можете увидеть, что arr1 стал указателем на int, поэтому вы не можете присвоить его указателю на массив int. Хотя указатель имеет значение ты хочешь, это неправильно тип.

Когда массив появляется как операнд & или же sizeof или же _Alignof, это автоматическое преобразование не происходит. Так &arr1 приводит к адресу массива.

Строковый литерал, который используется в инициализации, такой как char a[] = "abc"; обрабатывается специально и не преобразуется автоматически, как описано выше.

0
По вопросам рекламы [email protected]