我对指向数组的指针和正常指针以及如何访问感到困惑。 我试过这个......
int *ptr1, i;
int (*ptr2)[3];
int myArray[3] = {1, 1, 1};
int myArray1[5] = {1, 1, 1, 1, 1};
ptr1 = myArray;
ptr2 = myArray1;// compiles fine even though myArray1 contains 5 elements
// and ptr2 is pointing to array of 3 elements.
printf("%d",ptr2[3]); // prints some garbage.
为什么这句话是打印垃圾?什么是正确的陈述? 谁能解释一下?
答案 0 :(得分:4)
我们也可以将指向数组的指针声明为
int (*ptr)[]; // ptr is a pointer to array.
当你这样做时
ptr2 = myArray1;
编译器会向您发出警告消息。 Look boss types are not compatible.
在某些情况下,数组会衰减为指针。警告消息是因为,当数组衰减成指针时,衰减类型是指针。在这种情况下,当你做
ptr1 = myArray;
myArray衰变为int *
。
但是当你这样做时,
ptr2 = myArray1;
myArray1
衰减为int *
的指针,但ptr2
的类型为int (*)[]
。
为了避免警告,你应该说
ptr2 = &myArray1; //&myArray1 returns address of array and type is int(*)[].
为什么这句话会打印垃圾?什么是正确的陈述?任何人都可以解释一下吗?
printf("%d",ptr2[3]);// prints some garbage.
是的,但为什么呢?让我们先看看正确的陈述......(注意索引应该小于3)
printf("myArray1[%d] = %d\n", i, (*ptr2)[2]);
我们必须使用(*ptr2)[i]
来打印数组元素。这是因为,仅提及ptr2
,我们将获得数组的地址(而不是某些int
的地址)。通过取消引用它(*ptr2)
,我们将得到数组0th element
的地址。
答案 1 :(得分:1)
指针ptr2
是指向大小为3的int数组的指针
ptr2 = myArray1; // you may getting warning for this
应该是:
ptr2 = &myArray1; // use & operator
并且
printf("%d", ptr2[3]);
应该是:
printf("%d", (*ptr2)[2]); // index can't be 3 for three size array
// ^^^^^^^
需要*ptr2
周围的括号,因为[]
运算符的优先级高于*
解除引用运算符(如果使用指向int的指针,则不需要括号,如上面的代码)。
阅读Inconsistency in using pointer to an array and address of an array directly我已经解释了两个数组来访问数组元素。 (1)使用指向int(2)指向数组
的指针虽然找到ptr1 = myArray;
,但您只需使用ptr1[i]
访问数组元素(不是i
值应为0到4)
答案 2 :(得分:1)
int (*ptr2)[3];
这表示(*ptr2)
是包含整数数组开头的内存位置的标识符。或者,改写一下,ptr2
是一个地址。该地址包含一个值。该值本身就是一个int数组开头的地址。
所以当你写ptr2 = myArray1
时,你基本上是在说“我的地址持有人的地址是myArray1
”开头的地址。
因此,当您使用ptr2[3]
打印值时,您实际上正在打印myArray1
的内存地址的值,递增3*sizeof(ptr2)
个单位。这就是为什么它看起来像垃圾,它是一些内存地址。
print语句中应该包含(*ptr2)[3]
,这意味着“获取ptr2
的地址并获取存储在该地址的值。接下来,使用该第二个地址,将其递增{{1}并获取存储在该递增地址的值。“
C中的数组只不过是分配内存的连续区域。这就是为什么说:
3*sizeof(int)
与:
相同int *x = malloc(3*sizeof(int));
由于int x[3];
和[]
都取消引用指针,如果我们想要访问任一数组的第二个元素,我们可以写:
*
或
int value = x[1];
两个主要区别是int value = *x+sizeof(int); // Since *x would be index 0
表示法更容易阅读,但长度必须在编译时确定。然而,使用[]
/ *x
表示法,我们可以动态创建数组或任意长度。