我正在嘗試使用指標在 C 中列印一個二維陣列,但我沒有得到預期的輸出。
程式:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr 6; p )
{
printf("%d ", *p);
}
return 0;
}
輸出:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
你能告訴我我錯在哪里,因為輸出應該只是:
1 2 3 4 5 6
uj5u.com熱心網友回復:
你能告訴我哪里錯了嗎
的元素arr不是整數,而是 3 個整數的陣列。所以arr 6肯定是一個與您期望的地址不同的地址,因為指標算術以陣列中型別大小的倍數作業。
使用嵌套回圈遍歷多維陣列總是會更好;將其視為一個一維陣列int 會導致您在此處看到的那種混亂。代碼更難理解和驗證,不會變慢。
uj5u.com熱心網友回復:
n首先,當使用索引遍歷大小陣列時i,繼續的條件應該是i < n而不是i <= n,因為 C 中的陣列索引從0through開始n-1。
但是,您的代碼有一個更嚴重的錯誤:一維陣列可以“衰減”為指向元素型別的指標;然而,二維陣列衰減為指向一維陣列的指標。因此,在您的情況下,運算式中使用的指標型別arr 6是指向三個整數陣列的指標;此外,當6添加 時,該操作是根據指向物件的大小執行的,即sizeof(int) * 3- 因此,即使將 更改<=為<,您的運行也會遠遠超出陣列的實際范圍。
要使指標算術以正確的“單位”(即sizeof(int))作業,請在加法之前arr將 a 轉換為 a (并更改to ):int* <=<
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr 6; p ) {
printf("%d ", *p);
}
return 0;
}
uj5u.com熱心網友回復:
您試圖以錯誤的方式訪問該值,二維陣列在記憶體中保存為連續塊。因此,如果我們將 ptr 的值增加 1,我們將移動到分配的記憶體中的下一個塊。
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i ) {
printf("%d ", *(ptr i));
}
return 0;
uj5u.com熱心網友回復:
運算式中使用的陣列指示符(極少例外)被隱式轉換為指向其第一個元素的指標。
此陣列的陣列元素的型別
int arr[2][3];
是int [3]。所以指向陣列第一個元素的指標的型別為int ( * )[3]。
本次作業
p = arr;
where phas 型別int *不正確,因為賦值的運算元具有不兼容的指標型別。
至少您需要將正確的運算式轉換為int *類似的型別
p = ( int * )arr;
您需要在 for 回圈的條件中使用相同的轉換。那是代替
p <= arr 6
你必須寫
p < ( int * )arr 6
下面有一個演示程式,展示了如何使用指標將二維陣列輸出為二維陣列。
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr 2; p )
{
for ( int *q = *p; q != *p 3; q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
如果要將二維陣列輸出為一維陣列,則可以撰寫
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr 6; p )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
uj5u.com熱心網友回復:
在
for ( p = arr; p <= arr 6; p )
運算式arr,作為rvalue,是指向陣列第一個元素的指標(它的型別為int [3],因此每次增加該指標時,它都會向前移動三個int位置---一整行---,因此,arr 6點就在陣列的第六行之后(如果陣列應該有六行)您可以使用作為第一個地址的運算式來執行此操作(使用適當的顯式指標轉換,因為您將指標int與指標混合)第二行之后的陣列元素(以及陣列的行數)。int [3]arr 2
你也可以宣告
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux 1 will be the position of the second
* 2D array after this one */
然后
int *end = (int *)(aux 1);
或者干脆
int *end = (int *)(&arr 1); /* see below */
(注意arrand&arr都是指標并指向同一個地方,但它們的型別不同(arris of typeint (*)[3]和&arris of type int(*)[2][3])
因此,讓我們將您的代碼重寫為
for (p = (int *)arr; p < end; p )
要么
for (p = (int *)arr; p < (int *)&arr 1; p )
會起作用,在完整的陣列單元中進行微積分似乎比在行或單個單元格中更自然(并且您可以自由更改陣列的尺寸)
您的代碼將是:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p )
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(請注意,您必須使用<運算子而不是<=因為您不想列印 指向的值end,因為它位于陣列之外的一個位置)
最后注意:這將適用于真正的陣列,但不適用于宣告為陣列的函式引數,因為它們會衰減為指標,然后&arr不是指向陣列大小的資料的指標,而是引數本身的地址,即指向其他地方的陣列。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/430739.html
上一篇:手動為指標分配記憶體地址的問題
