我在C语言中学习数组和指针时感到困惑,为什么ch,&ch,&ch [0]恰好彼此相等,而sptr,&sptr和sptr [0]不是?这是我的源代码:
int main(void)
{
char ch[7] = { '1','2','3','4','5','6','0' };
char *sptr = "132456";
double db[4] = { 1.0,2.0,3.0,4.0 };
printf("\n%p %p %p\n", ch, &ch,&ch[0]);
printf("\n%p %p %p\n", sptr, &sptr,&sptr[0]);
printf("\n%p %p %p\n", db, &db,&db[0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我机器上的输入是:
00FDFD68 00FDFD68 00FDFD68
00037CD0 00FDFD5C 00037CD0
00FDFD34 00FDFD34 00FDFD34
Run Code Online (Sandbox Code Playgroud)
在大多数(尽管不是全部)上下文中,数组"衰减"为指向其第一个元素的指针.这就是为什么ch,并&ch[0]在你的榜样(数组元素访问具有比运营商"的地址为"更高的优先级,因此后者也可以写成相同&(ch[0])).
剩下的&ch是一个数组不会衰减成指针的情况; 相反,你得到了数组的地址.当然,这与数组的第一个元素的地址相同 - 但是,重要的是,它具有不同的类型; 它是类型char (*)[7],即指向具有7个元素的char数组的指针.另外两个指针是类型的char *,即指向个体的指针char.
既然sptr是一个指针,&sptr那个指针的地址自然会有所不同.&sptr[0]相当于sptr + 0,当然等于sptr.
你不明白为什么sptr并&sptr产生不同的地址表明对指针的误解.指针是一个固定大小的对象,其值可以引用(指向)特定类型的某个任意对象.因为它本身就是一个对象,所以可以使指针指向不同的对象.另一方面,数组变量始终(在其生命周期内)引用相同的数组对象.
在您的示例输出中:
00037CD0 00FDFD5C 00037CD0
Run Code Online (Sandbox Code Playgroud)
第一个值00037CD0是sptr点的位置- 也就是说,它是字符串常量"132456"的内存位置.第二个值00FDFD5C是sptr变量本身的地址.这表明在地址00FDFD5C处有一个指针对象,它保存值00037CD0.
从本质上讲,两种情况之间的区别归结为:
如果我们将其“绘制”出来,您的数组ch在内存中将如下所示:
+-----+-----+-----+-----+-----+-----+-----+ | '1'| '2'| '3'| '4'| '5'| '6'| '0'| +-----+-----+-----+-----+-----+-----+-----+ ^^ | | | &ch[1] | &ch ^ | &ch[0]
正如您所看到的,两者&ch都&ch[0]指向同一位置。但这两个表达式之间有一个重要的区别:是指向数组的&ch指针,而是指向数组中元素的指针。这两个指针具有不同的类型:具有类型而具有类型。即使两者都是指向同一位置的指针,类型的差异也会使其在语义上有很大不同。&ch[0]&chchar (*)[7]&ch[0]char *
现在来看看如何array融入这一切。对于任何数组或指针a和索引i,表达式a[i]等于*(a + i)。这意味着&a[i]等于&*(a + i)。地址运算符和解引用运算符相互抵消,这意味着&a[i]等于(a + i)。如果索引为零,则&a[0]等于(a + 0),但由于向任何内容添加零都是无操作,因此它也等于 ,而(a)等于a。因此&a[0]等于a. 当您看到有人说数组衰减为指向其第一个元素的指针时,这就是他们的意思。在表达式中使用数组a与使用 相同&a[0]。
在一个不相关的注释中,该数组ch可能是字符数组,但它不是字符串。这是因为在 C 语言中字符串实际上称为空终止字符串。在这种情况下,单词“null”不是空指针,而是整数(不是字符)零。
这意味着您不能使用ch任何需要字符串的函数,因为这会导致未定义的行为,因为它们超出了寻找终止符的范围。
| 归档时间: |
|
| 查看次数: |
466 次 |
| 最近记录: |