Похоже, вы получили множество ответов, пока я писал мой, но я мог бы также опубликовать мой ответ в любом случае, так что я не чувствую, что все это было зря ...
(все sizeof
результаты взяты из VC2012 - 32 бит сборки, размеры указателей будет, конечно, дважды с 64 битным построить)
size_t f0(int* I);
size_t f1(int I[]);
size_t f2(int I[2]);
int main(int argc, char** argv)
{
// A0, A1, and A2 are local (on the stack) two-by-two integer arrays
// (they are technically not pointers)
// nested braces not needed because the array dimensions are explicit [2][2]
int A0[2][2] = {0,1,2,3};
// nested braces needed because the array dimensions are not explicit,
//so the braces let the compiler deduce that the missing dimension is 2
int A1[][2] = {{0,1},{2,3}};
// this still works, of course. Very explicit.
int A2[2][2] = {{0,1},{2,3}};
// A3 is a pointer to an integer pointer. New constructs an array of two
// integer pointers (on the heap) and returns a pointer to the first one.
int **A3 = new int*[2];
// if you wanted to access A3 with a double subscript, you would have to
// make the 2 int pointers in the array point to something valid as well
A3[0] = new int[2];
A3[1] = new int[2];
A3[0][0] = 7;
// this one doesn't compile because new doesn't return "pointer to int"
// when it is called like this
int *A4_1 = new int[2][2];
// this edit of the above works but can be confusing
int (*A4_2)[2] = new int[2][2];
// it allocates a two-by-two array of integers and returns a pointer to
// where the first integer is, however the type of the pointer that it
// returns is "pointer to integer array"
// now it works like the 2by2 arrays from earlier,
// but A4_2 is a pointer to the **heap**
A4_2[0][0] = 6;
A4_2[0][1] = 7;
A4_2[1][0] = 8;
A4_2[1][1] = 9;
// looking at the sizes can shed some light on subtle differences here
// between pointers and arrays
A0[0][0] = sizeof(A0); // 16 // typeof(A0) is int[2][2] (2by2 int array, 4 ints total, 16 bytes)
A0[0][1] = sizeof(A0[0]); // 8 // typeof(A0[0]) is int[2] (array of 2 ints)
A1[0][0] = sizeof(A1); // 16 // typeof(A1) is int[2][2]
A1[0][1] = sizeof(A1[0]); // 8 // typeof(A1[0]) is int[2]
A2[0][0] = sizeof(A2); // 16 // typeof(A2) is int[2][2]
A2[0][1] = sizeof(A2[0]); // 8 // typeof(A1[0]) is int[2]
A3[0][0] = sizeof(A3); // 4 // typeof(A3) is int**
A3[0][1] = sizeof(A3[0]); // 4 // typeof(A3[0]) is int*
A4_2[0][0] = sizeof(A4_2); // 4 // typeof(A4_2) is int(*)[2] (pointer to array of 2 ints)
A4_2[0][1] = sizeof(A4_2[0]); // 8 // typeof(A4_2[0]) is int[2] (the first array of 2 ints)
A4_2[1][0] = sizeof(A4_2[1]); // 8 // typeof(A4_2[1]) is int[2] (the second array of 2 ints)
A4_2[1][1] = sizeof(*A4_2); // 8 // typeof(*A4_2) is int[2] (different way to reference the first array of 2 ints)
// confusion between pointers and arrays often arises from the common practice of
// allowing arrays to transparently decay (implicitly convert) to pointers
A0[1][0] = f0(A0[0]); // f0 returns 4.
// Not surprising because declaration of f0 demands int*
A0[1][1] = f1(A0[0]); // f1 returns 4.
// Still not too surprising because declaration of f1 doesn't
// explicitly specify array size
A2[1][0] = f2(A2[0]); // f2 returns 4.
// Much more surprising because declaration of f2 explicitly says
// it takes "int I[2]"
int B0[25];
B0[0] = sizeof(B0); // 100 == (sizeof(int)*25)
B0[1] = f2(B0); // also compiles and returns 4.
// Don't do this! just be aware that this kind of thing can
// happen when arrays decay.
return 0;
}
// these are always returning 4 above because, when compiled,
// all of these functions actually take int* as an argument
size_t f0(int* I)
{
return sizeof(I);
}
size_t f1(int I[])
{
return sizeof(I);
}
size_t f2(int I[2])
{
return sizeof(I);
}
// indeed, if I try to overload f0 like this, it will not compile.
// it will complain that, "function 'size_t f0(int *)' already has a body"
size_t f0(int I[2])
{
return sizeof(I);
}
да, этот образец имеет тонны подписанного/без знака Int рассогласования, но эта часть не относится к вопрос. Кроме того, не забудьте delete
все созданные с new
и delete[]
все созданные с new[]
EDIT:
«Что происходит, когда я A+1
?» - Я пропустил это раньше.
Операции, подобные этому, будут называться «арифметикой указателей» (хотя я обратился к вершине своего ответа, что некоторые из них не являются указателями, но они могут превращаться в указатели).
Если у меня есть указатель P
на массив someType
, то индекс доступа P[n]
точно так же, как с помощью этого синтаксиса *(P + n)
. Компилятор учитывает размер указателя, указываемого в обоих случаях. Таким образом, полученный код операции действительно сделает что-то вроде этого для вас *(P + n*sizeof(someType))
или эквивалентно *(P + n*sizeof(*P))
, потому что физический процессор не знает и не заботится обо всех наших «типах». В конце концов, все смещения указателя должны быть байтом. Для согласованности имена массивов, такие как указатели, работают одинаково.
Возвращаясь к выше образцов: A0
, A1
, A2
и A4_2
ведут себя одинаково с указателем арифметики.
A0[0]
такое же, как *(A0+0)
, который ссылается на первый int[2]
из A0
аналогично:
A0[1]
такое же, как *(A0+1)
, который компенсирует «указатель» на sizeof(A0[0])
(т.е.8, см. Выше), и он заканчивается ссылкой на второй int[2]
от A0
A3
действует несколько иначе. Это связано с тем, что A3
является единственным, который не хранит все 4 типа массива 2 на 2 смежно. В моем примере A3
указывает на массив из 2 указателей int, каждый из которых указывает на полностью отделяет массивы двух ints. Использование A3[1]
или *(A3+1)
по-прежнему будет направлять вас ко второму из двух массивов int, но это будет сделано путем смещения только 4 байта с начала A3 (с использованием 32-битных указателей для моих целей), который дает вам указатель, который сообщает вам где можно найти второй массив с двумя int. Я надеюсь, что в этом есть смысл.
Где вы нашли примеры? –
@ Cheersandhth.-Alf, в основном из вопросов, которые мне дал мой профессор. Он намеренно пытается иногда сбивать с толку. – n0pe
@clcto, да, но я пытаюсь понять, что именно такое A, поэтому я могу нарисовать небольшую диаграмму памяти и работать со структурой. – n0pe