为了账号安全,请及时绑定邮箱和手机立即绑定

数组是指针?

/ 猿问

数组是指针?

C++ C
慕码人8056858 2019-08-09 09:55:06

数组是指针?

数组和指针在C和C ++中的实现方式是否不同?我遇到过这个问题,因为在这两种情况下我们都从元素的起始地址访问元素。所以,他们之间应该有密切的关系。请解释它们之间的确切关系。谢谢。



查看完整描述

4 回答

?
Codeli

  首先我要告诉你,数组不是指针!!这在C和C++都是这样的。

  数组是用来存储数据的,例如 int a[]={1,2,3,4,5};这里的数组存储了5个数字。

再来看指针,我们先看指针变量。

int a=10;
int *b=&a;   //注意这个*和&,*是指针的标志,&是取地址符,用来取a的地址

看见区别了吧,指针用来存储一个变量 or 数组 的地址!  每一个变量都有一个独立的地址,就像门牌号一样。

指针数组和指针变量一个道理,这里就不在叙述。这里给一个案例:

char *a[9]={"这","是","一","个","指","针","数","组"}   //注意,这里存的不是字符,而是字符的地址!
for(int i=1;i<=8;i++)
{
    cout<<a[i];   // 注意这里不需再用*
}

 是不是出现了Warning?其实char *的背后意义是:给我个字符串,我要修改它!但实际上,char * 常量是无法被修改的。所以我们要修改成const char *,它的意思就是:给我个字符串,我只要读取它!这样就不会发生“纠纷”了。

  至于有的人说,C中的数组和指针等价,我就给你个片段吧!

一个 T 的数组类型的左值如果出现在表达式中会蜕变为一个指向数
组第一个成员的指针(除了三种例外情况); 结果指针的类型是 T 的
指针。

至于它的意思,查度娘!

查看完整回答
反对 回复 2019-08-09
  • onemoo
    onemoo
    我强烈怀疑本帖的题主和其他回答者都是机器人! 他们在这里发的内容完全是照搬机翻了爆栈的这个帖子 https://stackoverflow.com/questions/3959705/arrays-are-pointers 不知你发现没有,进来出现了很多这样的机器人,问答区里遍地都是。 因为他们发的内容明显是机翻的,一开始我以为是有人在恶意刷分,后来发现这些用户的积分几乎都是负分(不知是如何被扣分的) 又因为发现这么多帐号是在有组织地搬运stackoverflow的帖子,这甚至一度让我怀疑这些是本站自己搞的僵尸用户,为了刷热度... 现在这样的怪象依然存在
?
30秒到达战场

让我们首先得到重要的东西:数组不是指针。数组类型和指针类型是完全不同的东西,编译器会对它们进行不同的处理。

出现混淆的地方是C如何处理数组表达式N1570

6.3.2.1左值,数组和函数指示符

... 
3除了当它是的操作数sizeof运算符,_Alignof操作者,或一元&运算符,或者是用于初始化数组文本的字符串,其具有输入“”的阵列的表达类型 “”被转换为表达式用类型“”指针键入指向阵列对象的初始元素,不是左值“”。如果数组对象具有寄存器存储类,则行为未定义。

我们来看看以下声明:

int arr[10] = {0,1,2,3,4,5,6,7,8,9};int *parr = arr;

arr是一个10元素的数组int; 它指的是一个足以存储10个int值的连续内存块。第二个声明中的表达式 arr是数组类型,但由于它不是&或的操作数sizeof而且它不是字符串文字,表达式的类型变为“指向int”,而值是第一个元素的地址或者&arr[0]

parr是指向int的指针; 它指的是一块足以容纳单个int对象地址的内存块。arr如上所述,它被初始化为指向第一个元素。

这是一个假设的存储器映射,显示了两者之间的关系(假设16位整数和32位地址):

对象地址0x00 0x01 0x02 0x03------ ------- ----------------------
   arr 0x10008000 0x00 0x00 0x00 0x01
                 0x10008004 0x00 0x02 0x00 0x03
                 0x10008008 0x00 0x04 0x00 0x05
                 0x1000800c 0x00 0x06 0x00 0x07
                 0x10008010 0x00 0x08 0x00 0x09
  parr 0x10008014 0x10 0x00 0x80 0x00

这些类型对于像sizeof和的事物很重要&sizeof arr == 10 * sizeof (int)在这种情况下,它是20,而sizeof parr == sizeof (int *)在这种情况下,它是4.类似地,表达式的类型&arrint (*)[10],或指向10元素数组的指针int,而&parris 的类型int **或指向指针的指针int

请注意,表达式arr&arr将产生相同的(第一个元素的地址arr),但表达式的类型是不同的(int *int (*)[10]分别)。这在使用指针运算时有所不同。例如,给定:

int arr[10] = {0,1,2,3,4,5,6,7,8,9};int *p = arr;int (*ap)[10] = &arr;printf("before: arr = %p, p = %p, ap = %p\n", (void *) arr, (void *) p, (void *) ap);p++;ap++;printf("after: arr = %p, p = %p, ap = %p\n", (void *) arr, (void *) p, (void *) ap);

“之前”行应该为所有三个表达式打印相同的值(在我们的假设图中0x10008000)。“本经”行应该表现出三个不同的值:0x10008000, 0x10008002(基地+ sizeof (int))和0x10008014(基地+ sizeof (int [10]))。

现在让我们回到上面的第二段:在大多数情况下,数组表达式转换为指针类型。我们来看下标表达式arr[i]。由于表达式arr不是作为任何一个sizeof或的操作数出现&,并且因为它不是用于初始化另一个数组的字符串文字,所以它的类型从“10元素数组int”转换为“指向int”,以及下标操作正在应用于此指针值。实际上,当您查看C语言定义时,您会看到以下语言:

6.5.2.1数组下标
... 
2后缀表达式后跟方括号[]中的表达式是数组对象元素的下标名称。下标运算符[]的定义是E1 [E2](*((E1)+(E2)))相同。由于适用于binary +运算符的转换规则,如果E1是数组对象(等效地,指向数组对象的初始元素的指针)并且E2是整数,则E1 [E2]指定E2的2个元素。E1(从零开始计数)。

实际上,这意味着您可以将下标运算符应用于指针对象,就像它是一个数组一样。这就像代码一样

int foo(int *p, size_t size){
  int sum = 0;
  int i;
  for (i = 0; i < size; i++)
  {
    sum += p[i];
  }
  return sum;}int main(void){
  int arr[10] = {0,1,2,3,4,5,6,7,8,9};
  int result = foo(arr, sizeof arr / sizeof arr[0]);
  ...}

它的工作方式。 main正在处理一个数组int,而foo正在处理一个指针int,但两个都能够使用下标运算符,就好像它们都处理数组类型一样。

它还意味着数组下标是可交换的:假设a是一个数组表达式并且i是一个整数表达式,a[i]并且i[a]都是有效的表达式,并且两者都将产生相同的值。


查看完整回答
反对 回复 2019-08-09
?
繁星淼淼

不了解C ++。对于C来说,c-faq的答案要比以往任何时候都好得多。

来自c-faq的小片段:

6.3那么C中“指针和数组的等价”是什么意思?

[...]

具体而言,等价的基石是这个关键定义:

对表达式中出现的array-of-T类型的对象的引用将(有三个例外)衰减为指向其第一个元素的指针; 结果指针的类型是指向T的指针。

[...]


查看完整回答
反对 回复 2019-08-09
?
饮歌长啸

在C ++中根据C ++标准4.2:

可以将“N T数组”或“T的未知数组的数组”类型的左值或右值转换为“指向T的指针”的右值。结果是指向数组的第一个元素的指针。


查看完整回答
反对 回复 2019-08-09

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信