为什么不能将数组的地址分配给指针?

时间:2020-03-20 22:12:38

标签: c++ arrays pointers declaration implicit-conversion

int q[10]={0};
cout << q << endl;
cout << &q << endl;
cout << &q[0] << endl;

输出是

0x7fffd4d2f860 
0x7fffd4d2f860 
0x7fffd4d2f860 

现在当我这样做时->

int *r=q;    // allowed
int *r=&q[0] // allowed
int *r=&q    // not allowed

为什么本质上是同一件事,不允许第三次分配?

4 个答案:

答案 0 :(得分:9)

如果您声明的数组类似

T a[N];

其中T是某种类型说明符,则将声明指向数组的指针,如

T ( *p )[N] = &a;

一般规则如下。如果您有一个多维数组(包括一维数组),例如

T a[N1][N2][N3];

然后您可以像这样重写此声明

T ( a[N1] )[N2][N3];

要获得指向数组第一个元素的指针,只需按以下方式替换括号中的内容

T ( *p )[N2][N3] = a;

如果要获取指向整个数组的指针,则像这样重写数组的声明

T ( a )[N1][N2][N3];

并进行替换

T ( *p )[N1][N2][N3] = &a;

将此与标量对象的声明和指向它的指针进行比较。

例如

T obj;

您可以像这样重写声明

T ( obj );

现在要获得指向您可以编写的对象的指针

T ( *p ) = &obj;

当然,在这种情况下,括号是多余的,并且上面的声明等效于

T *p = &obj;

关于此代码段

int q[10]={0};
cout << q << endl;
cout << &q << endl;
cout << &q[0] << endl;

及其输出

0x7fffd4d2f860 
0x7fffd4d2f860 
0x7fffd4d2f860 

然后将表达式中使用的具有极少数例外的数组指示符转换为指向其第一个元素的指针。

实际上,这些语句中的两个表达式q&q[0]

cout << q << endl;
cout << &q[0] << endl;

是等效的。另一方面,数组本身的地址是该数组占用的内存范围的地址。并且在范围的开头有数组的第一个元素。因此,这三个表达式给出了相同的结果:数组所占用的内存范围的地址。

答案 1 :(得分:3)

为什么本质上是同一件事,不允许第三次分配?

因为C ++语言具有一个称为“类型安全”的功能。有一个类型系统可以帮助您保持程序声音的逻辑。

一个特殊的规则是,不能使用任意指针类型来初始化其他不兼容类型的指针。在这种情况下,您有一个尝试键入int的指针(即int*),并尝试使用类型为10 int的数组类型的指针(即int(*)[10])来初始化。一种类型不能隐式转换为另一种类型,因此程序格式错误。

那为什么cout在这三种情况下都打印相同的东西?

因为所有指针都具有相同的值。数组第一个元素的第一个字节与整个数组的第一个字节相同。

碰巧的是,流插入运算符完全相同地处理所有指针类型 1 ,因此具有相同值但类型不同的指针会产生相同的输出。

1 指向字符类型的指针是一个例外。他们的待遇完全不同。


为什么不能将数组的地址分配给指针?

实际上,我们可以将数组的地址分配给指针。我们只是不能将数组(或与此有关的任何其他对象)的地址分配给错误类型的指针。在这种情况下,我们需要一个指向数组的指针:

int (*r)[10] = &q;

答案 2 :(得分:1)

您不能进行第三次分配,因为&q的类型是int (*)[10],它与int* r的类型不兼容。

cout << &q的输出未显示&q的类型。请参阅this文档链接。

答案 3 :(得分:1)

import React from 'react'; import Tooltip from '@material-ui/core/Tooltip'; import CONSTANTS from '../../../../../constants'; import Icon from '../../../../shared/components/common/Icon'; import { CollapseButtonWrapperStyled, CollapseButtonIconWrapperStyled, CollapseButtonStyled } from './styled'; const { ICONS } = CONSTANTS; const CollapseButton = props => { const { intl: { formatMessage }, collapsed, onClick } = props; return ( <CollapseButtonWrapperStyled onClick={onClick}> <Tooltip title={collapsed ? formatMessage({ id: 'general.sideBar.help.expand' }) : formatMessage({ id: 'general.sideBar.help.collapse' })} placement="right" enterDelay={500} > <CollapseButtonStyled> <CollapseButtonIconWrapperStyled> <Icon path={ICONS.DOUBLE_ARROW_LEFT} size={16} viewBoxSize={24} /> </CollapseButtonIconWrapperStyled> </CollapseButtonStyled> </Tooltip> </CollapseButtonWrapperStyled> ); }; CollapseButton.propTypes = propTypes; export default CollapseButton; 是固定长度的数组。在表达式decays中将q本身指定为指向q的第一个元素的指针。因此,q 衰减q返回的指针值。另一方面,&q[0]返回&q变量本身的内存地址,对于数组,其第一个元素占用相同的内存地址。

q定义了一个operator<<(void*)std::ostream可以接受(几乎)任何类型的指针。由于您的所有三个void*调用都解析为相同的内存地址,并且有一个cout可以接受所有三种类型的指针,因此这三个调用都打印相同的数字。

关于您的作业:

  • operator<<q,它会衰减变成int[10],这就是int*起作用的原因。

  • int *r=q;取消引用&q[0]以访问其第一个元素q,然后获取该元素的地址,产生一个int,这就是int*起作用的原因。

  • ,因为int *r=&q[0];qint[10]&q,不会衰减成为{{1} },这就是int(*)[10]不起作用的原因。您必须使用正确的类型声明int*

    int *r=&q;