Объясните двусмысленность указателей в C?
#include<stdio.h>
main()
{ int x[3][5]={{1,2,10,4,5},{6,7,1,9,10},{11,12,13,14,15}};
printf("%d\n",x);
printf("%d\n",*x); }
Здесь первый printf напечатает адрес первого элемента.
Так почему бы не второй printf напечатать значение по адресу x i.e первое значение.
Чтобы напечатать значение, мне нужно написать ** x.
Ответы
Ответ 1
Для указателей x[0]
совпадает с *x
. Из этого следует, что *x[0]
совпадает с **x
.
В *x[0]
:
x
является int[3][5]
, который преобразуется в int(*)[5]
при использовании в выражении. Таким образом, x [0] является lvalue типа int[5]
(первая 5-элементная "строка" ), которая снова преобразуется в int*
и разыменовывается ее первым элементом.
*x
оценивается по тем же строкам, за исключением того, что первое разыменование выполняется со звездочкой (в отличие от индексации), и нет второго разыменования, поэтому мы заканчиваем lvalue типа int[5]
, который передан в printf
как указатель на его первый элемент.
Ответ 2
Массивы, используемые в качестве аргументов для функций, распадаются на указатели на первый элемент массива. При этом тип объекта, который x
распадается, является указателем на первый подматрица, который является указателем на массив из int
или в основном int (*)[5]
. Когда вы вызываете printf("%d\n",*x)
, вы не подаете целочисленное значение в printf
, а скорее указатель на первый под-массив x
. Поскольку этот субмассив также распадается на указатель на первый элемент под-массива, вы можете сделать **x
для разыменования этого последующего указателя и получить в первом элементе первого подматрица x
. Это фактически то же самое, что и *x[0]
, которое по приоритету оператора будет индексироваться в первый под-массив x
, а затем разыменовать указатель на первый элемент подматрицы, в который будет впадать первый подматрица.
Ответ 3
Из-за типа *x
есть указатель на массив из 5 ints. Итак, вам нужно еще одно разыменование, чтобы получить первый элемент
PS:
#include <typeinfo>
#include <iostream>
typedef int arr[5]; // can't compile if put arr[4] here
void foo(arr& x)
{
}
int main()
{
int x[3][5]={{1,2,10,4,5},{6,7,1,9,10},{11,12,13,14,15}};
std::cout << typeid(*x).name() << std::endl;// output: int [5]
foo(x[0]);
return 0;
}
Ответ 4
Подумайте о двухмерном массиве как массиве указателей, причем каждый элемент массива указывает на первый элемент в другом массиве. Когда вы разыскиваете x
, вы получаете значение, которое находится в ячейке памяти, на которую указывает x... указатель на первый int
в массиве int
s. Когда вы разыгрываете этот указатель, вы получите первый элемент.