我在C中遇到了一些“怪异”的行为,至少是我没想到的。请考虑以下代码行:
int arrayB[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
printf("%d\n", (arrayB+1)[1]);
此工作正常,因为(arrayB + 1)[1]
转换为*(arrayB+1 +1)
,这是arrayB
的第三个元素(因此它会按预期打印3个)
但是,请考虑下面的代码,我在其中初始化一个名为arrayA
的2D数组(包含5个10个整数的数组,每个{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
)
int ** arrayA = malloc(sizeof(int *) * 5);
for (int i = 0; i < 5; i++) {
arrayA[i] = malloc(sizeof(int) * 10);
for (int j = 0; j < 10; j++) {
arrayA[i][j] = j;
}
}
printf("%d\n", *(arrayA+1)[2]);
此代码不会发出警告,并声称*(arrayA+1)[2]
是int类型。但是..它似乎应该是(因为数组下标比解引用运算符具有更高的优先级),*(arrayA+1)[2]
转换为类型为*(arrayA+3)
的{{1}},因为int *
是一个arrayA
,更进一步说,这是允许的:
int **
但这怎么可能?好像我正在为*(arrayA+1)[2] = 1;
分配int
...这通常会引发警告。
答案 0 :(得分:3)
似乎......
*(arrayA+1)[2]
会转换为*(arrayA+3)
不,你放弃了*
。 *(arrayA+1)[2]
转换为**(arrayA+3)
,这确实是int
。
答案 1 :(得分:0)
我们讨论int ** arrayA(2D)。
arrayA是int **,所以arrayA + x也是int **。
* arrayA或arrayA [i]是int *,是一个线性数组(1D)。
所以,*(arrayA + 1)[2],任何优先级都是值而不是地址。
答案 2 :(得分:-1)
除了指针修正,你可以自由地声明一个指向指针指向的指针(例如int **arrayA;
),并分配指针,然后分配内存和将块分配给每个单独的指针,在处理每行中固定数量的元素时不需要这样做。您可以简单地声明一个指向数组的指针 - 类型(例如int (*arrayA)[10];
并分配一次。例如:
#include <stdio.h>
#include <stdlib.h>
#define ASZ 5
void *xmalloc (size_t s) {
void *memptr = malloc (s);
if (memptr == 0) {
fprintf (stderr, "xmalloc() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
return memptr;
}
int main (void) {
int i, j;
int (*arrayA)[ASZ] = xmalloc (sizeof *arrayA * ASZ);
for (i = 0; i < ASZ; i++) {
for (j = 0; j < ASZ; j++) {
arrayA[i][j] = j+i;
}
}
for (i = 0; i < ASZ; i++) {
if (!i) putchar ('\n');
for (j = 0; j < ASZ; j++) {
printf (" %2d", arrayA[i][j]);
}
putchar ('\n');
}
printf("\n *(arrayA+1)[2] = %d\n\n", *(arrayA+1)[2]);
free (arrayA);
return 0;
}
(不要忘记验证你的内存分配。使用像xmalloc
这样的帮助可以让生活更轻松。
示例使用/输出
$ ./bin/arr2dderef
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
*(arrayA+1)[2] = 3
不要忘记在Linux上使用内存错误检查程序验证内存使用情况,例如valgrind
,并且在不再需要内存时不要忘记释放内存。 (是的,它会在exit
上自动释放,但现在养成了占用每个字节的习惯,以后你会为自己省去很多悲伤。
$ valgrind ./bin/arr2dderef
==28392== Memcheck, a memory error detector
==28392== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==28392== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==28392== Command: ./bin/arr2dderef
==28392==
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
*(arrayA+1)[2] = 3
==28392==
==28392== HEAP SUMMARY:
==28392== in use at exit: 0 bytes in 0 blocks
==28392== total heap usage: 1 allocs, 1 frees, 100 bytes allocated
==28392==
==28392== All heap blocks were freed -- no leaks are possible
==28392==
==28392== For counts of detected and suppressed errors, rerun with: -v
==28392== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)