Nas*_*Ohi 7 c++ arrays pointers
int (*arr)[5]means arr是一个包含5个整数的指针数组.现在究竟是什么指针?
如果我声明指向第一个元素的指针int arr[5]在哪里,它是否相同arr?
是arr从两个例子是一样的吗?如果没有,那么究竟什么是指向数组?
Mar*_* A. 11
先关闭一些理论(你可以跳到"答案"部分,但我建议你也读一下):
int arr[5]
Run Code Online (Sandbox Code Playgroud)
这是一个数组,"arr" 不是指向数组第一个元素的指针.在特定情况下(即将它们作为左值传递给函数),它们会衰减成指针:你失去了调用sizeof它们的能力.
在正常情况下,数组是一个数组,指针是一个指针,它们是两个完全不同的东西.
当处理衰减的指针和指向你所编写的数组的指针时,它们的行为完全相同但有一个警告:类型为T的数组可以衰减为类型为T的指针,但只有一次(或一个深度级).新创建的腐朽类型不能进一步腐烂到其他任何东西.
这意味着像二维数组一样
int array1[2][2] = {{0, 1}, {2, 3}};
Run Code Online (Sandbox Code Playgroud)
不能传递给
void function1(int **a);
Run Code Online (Sandbox Code Playgroud)
因为它意味着两级衰变并且不允许(你将失去阵列元素的布局).以下将改为:
void function1(int a[][2]);
void function1(int a[2][2]);
Run Code Online (Sandbox Code Playgroud)
如果将一维数组作为左值传递给函数,则可以将其衰减为一个简单的指针,在这种情况下,您可以像使用任何其他指针一样使用它.
回答你的问题:
int (*arr)[5]
Run Code Online (Sandbox Code Playgroud)
这是一个指向数组的指针,您可以将"作为5个整数的数组"视为其类型,即您不能使用它指向3个整数的数组.
int arr[5]
Run Code Online (Sandbox Code Playgroud)
这是一个数组,除非将它作为左值传递,否则它将始终表现为数组
int* ptrToArr = arr;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,数组衰减(我引用上面的所有例外),你得到一个指针,你可以随意使用它.
并且:不,他们不相等,否则将允许这样的事情
int (*arr)[5]
int* ptrToArr = arr; // NOT ALLOWED
Error cannot convert ‘int (*)[5]’ to ‘int*’ in initialization
Run Code Online (Sandbox Code Playgroud)
他们都是指针,但区别在于他们的类型.
指向数组的指针和指向数组第一个元素的指针是不同的。在 的情况下int (*arr)[5],arr是指向 的内存块的指针5 int。取消引用arr将给出整行。在 的情况下int arr[5],arr衰减为指向第一个元素的指针。取消引用arr将给出第一个元素。
\n在这两种情况下,起始地址相同,但两个指针的类型不同。
\n\n\n如果我声明指向第一个元素的指针在
\nint arr[5]哪里,是否相同?两个例子arr是一样的吗?arr如果不是,那么指向数组的指针到底是什么?
否。要理解这一点,请参阅函数1的图表:
\n\nvoid f(void) {\n int matrix[4][2] = { {0,1}, {2,3}, {4,5}, {6,7} };\n char s[] = "abc";\n int i = 123;\n int *p1 = &matrix[0][0];\n int (*p2)[2] = &matrix[0];\n int (*p3)[4][2] = &matrix;\n /* code goes here */\n}\nRun Code Online (Sandbox Code Playgroud)\n\n
所有三个指针当然都允许您找到 in 0,matrix[0][0]如果您将这些指针转换为 \xe2\x80\x98byte 地址\xe2\x80\x99 并使用指令%pin打印它们printf(),那么这三个指针很可能会产生相同的输出(在典型的现代计算机上)。但int *指针p1只指向单个int,如黑色圆圈所示。红色指针 ,p2其类型为int (*)[2],指向两个ints,而蓝色指针(指向整个矩阵的指针)确实指向整个矩阵。\n这些差异会影响指针算术和一元*(间接)运算符。既然p1指向一单int,p1 + 1就前进一单int。黑色圆圈1只有 1 一样大int,并且*(p1 + 1)只是下一个 int,其值为 1。同样,sizeof *p1只是sizeof(int)(可能是 4)。
然而,由于p2指向 int\xe2\x80\x99 的整个 \xe2\x80\x98array 2 ,因此p2 + 1将向前移动一个这样的 array。结果将是一个指向围绕该对的红色圆圈的指针{2,3}。由于间接运算符的结果是一个对象,*(p2 + 1)因此是整个数组对象,这可能属于该规则的范围。如果它确实符合规则,则该对象将变成指向其第一个元素(即int当前持有的)的指针2。如果它不符合规则(例如, in sizeof *(p2 + 1),它将对象放入对象上下文中),它将保留整个数组对象。这意味着sizeof *(p2 + 1)(sizeof *p2当然也是)是sizeof(int[2])(可能是 8)。
1以上内容摘自《关于数组和指针的更多词汇》。
\n指向数组的指针是指向某种类型数组的指针.类型包括元素的类型以及大小.您不能为其分配不同类型的数组:
int (*arr)[5];
int a[5];
arr = &a; // OK
int b[42];
arr = &b; // ERROR: b is not of type int[5].
Run Code Online (Sandbox Code Playgroud)
指向数组第一个元素的指针可以指向任何具有正确元素类型的数组的开头(事实上,它可以指向数组中的任何元素):
int* arr;
int a[5];
arr = &a[0]; // OK
int b[42];
arr = &b[0]; // OK
arr = &b[9]; // OK
Run Code Online (Sandbox Code Playgroud)
请注意,在C和C++中,数组在某些上下文中衰减为指向其元素类型的指针.这就是为什么可以这样做的原因:
int* arr;
int a[5];
arr = a; // OK, a decays to int*, points to &a[0]
Run Code Online (Sandbox Code Playgroud)
在这里,类型arr(int*)是不一样的,即a(int[5]),但a衰减到一个int*指向它的第一个元素,使得分配的法律.
在运行时,无论指针指向什么,指针都是“只是指针”,区别在于语义。与指向元素的指针相比,指向数组的指针传达了不同的含义(给编译器)
在处理指向数组的指针时,您指向的是指定大小的数组-编译器将确保您只能指向该大小的数组。
即该代码将编译
int theArray[5];
int (*ptrToArray)[5];
ptrToArray = &theArray; // OK
Run Code Online (Sandbox Code Playgroud)
但这会中断:
int anotherArray[10];
int (*ptrToArray)[5];
ptrToArray = &anotherArray; // ERROR!
Run Code Online (Sandbox Code Playgroud)
在处理指向元素的指针时,您可以指向内存中具有匹配类型的任何对象。(它甚至不一定需要位于数组中;编译器不会做任何假设或以任何方式限制您)
即
int theArray[5];
int* ptrToElement = &theArray[0]; // OK - Pointer-to element 0
Run Code Online (Sandbox Code Playgroud)
和..
int anotherArray[10];
int* ptrToElement = &anotherArray[0]; // Also OK!
Run Code Online (Sandbox Code Playgroud)
总而言之,数据类型int*并不暗示对数组有任何了解,但是数据类型int (*)[5]暗示着一个数组,该数组必须恰好包含5个元素。
| 归档时间: |
|
| 查看次数: |
3189 次 |
| 最近记录: |