我在这里阅读了有关指针和数组等效性的各种文章和问题。几乎每篇文章都解释不同。我知道数组和指针是强相关的,而下面是我的指针和数组等效的实验,包括解释给定行为的注释(如果我在某处错了,请随时纠正我)。我的问题是:数组只是常量指针还是还有其他差异?
#include <stdio.h>
int main ()
{
// declaring array this way in fact declares a pointer with name "a" which points to the first element in the array:
int a[] = {0,1,2,3,4};
// assigning an array to the pointer in fact assigns the address of the first array element to the pointer, those two are thus equivalents:
int *pa1 = a;
int *pa2 = &a[0];
printf("########################\n");
// REFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%p\n", (a+0)); // a+0 == 0+a
printf("%p\n", a);
printf("%p\n", &a[0]);
printf("%p\n", &0[a]); // a+0 == 0+a
printf("########################\n");
// DEREFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%d\n", *(a+0)); // a+0 == 0+a
printf("%d\n", *a);
printf("%d\n", a[0]);
printf("%d\n", 0[a]); // a+0 == 0+a
printf("########################\n");
// REFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%p\n", (a+1));
printf("%p\n", &a[1]);
// REFERENCING: pointers can use array syntax (following are equivalents)
printf("%p\n", (pa1+1));
printf("%p\n", &pa1[1]);
printf("########################\n");
// DEREFERENCING: assigning values via pointers using pointer/array syntax (following are equivalents)
*(pa1+1) = *(pa1+1) + 10;
pa2[1] = pa2[1] + 10;
// DEREFERENCING: arrays can use pointer syntax (following are equivalents)
printf("%d\n", *(a+1));
printf("%d\n", a[1]);
printf("%d\n", 1[a]);
// DEREFERENCING: assigning values via arrays using pointer/array syntax (following are equivalents)
*(a+2) = *(a+2) + 10;
a[2] = a[2] + 10;
// DEREFERENCING: pointers can use array syntax (following are equivalents)
printf("%d\n", *(pa1+2));
printf("%d\n", pa1[2]);
printf("%d\n", 2[pa1]);
printf("########################\n");
// REFERENCING: those two pointers points to the same address
printf("%p\n", pa1);
printf("%p\n", pa2);
// DEREFERENCING: those two pointers points to the same address
printf("%d\n", *pa1);
printf("%d\n", *pa2);
printf("########################\n");
// This is correct:
pa1++;
printf("%p\n", pa1);
printf("%d\n", *pa1);
printf("%p\n", pa2);
printf("%d\n", *pa2);
printf("########################\n");
return 0;
}
我会说数组只是常量指针,唯一误导我的是当我尝试递增数组和常量指针时错误消息不同,这就是我的意思:
#include <stdio.h>
int main (){
int var1=0;
int * const ptr;
int a[] = {0,1,2,3,4,5};
// This gives an error:
// error: increment of read-only variable ‘ptr’
ptr++;
// This gives an error:
// error: lvalue required as increment operand
a++;
return 0;
}
如果它们不一样,请你发布一些这种差异显而易见的情况吗?
答案 0 :(得分:3)
阵列和指针是完全不同的动物。
在大多数情况下,表达式类型为&#34; N元素数组T
&#34;将被转换(&#34;衰减&#34;)到类型为&#34;指向T
&#34;的表达式,但数组对象本身不是指针。
此行为源于B语言,从中派生出C语言。在B中,数组对象是指针,下标操作a[i]
被解释为*(a + i)
(偏移i
个元素来自{{1}中存储的地址},取消引用结果)。
Ritchie保留了a
语义,但摆脱了显式指针; C将数组表达式转换为指针表达式(除非数组表达式是一元*(a + i)
或&
运算符的操作数)。
答案 1 :(得分:1)
您可以假装,数组与常量指针相同,但实际上它们是不同的类型。一个值得注意的差异是sizeof
运算符的结果。例如:
#include <stdio.h>
int main(void)
{
int a[] = {0, 1, 2, 3, 4, 5};
int * const p = a;
printf("sizeof(a) = %zu\n", sizeof(a));
printf("sizeof(p) = %zu\n", sizeof(p));
}
对于前者,您将获得阵列的总大小。假设sizeof(int) = 4
,它会打印24
。 OTOH,对于后者,你只需得到int
指针的大小。
此外,您不能将数组初始值设定项用于指针变量:
int * const p = {0, 1, 2, 3, 4, 5};
如果您使用-pedantic-errors
标志设置,会导致编译器错误,例如:
错误:标量初始值设定项中的多余元素
另一个重要的区别是在结构赋值期间,每个元素的数组都被复制:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct threeNumbers {
int t[3];
} a = {{1, 2, 3}}, b = {{4, 5, 6}};
int main(void)
{
a = b;
a.t[0] = 100;
printf("%d\n", a.t[0]); // prints 100
printf("%d\n", b.t[0]); // prints 4
}
指针不是这种情况。具有const指针的结构不能彼此分配。对于非const指针成员,仅复制地址。如果指针设置为malloc
,则可能导致内存泄漏。