c++ - What is the advantage of a pointer to the base address of an array instead of pointer to the first element?
问题描述
Following is a code snippet showing a pointer to the base of an array and a pointer to the element;
1st case:
/* Pointer to an array of 10 integers */
int arr[10]
int (*ptr)[10];
ptr = & arr; //points to the base address of an array of 10 integers
for (i = 0; i < 10; i++) //prints the values
printf("%d\n", *(*ptr + i));
2nd case:
/* Pointer to an array element*/
int arr[10];
int *ptr;
ptr = arr; //Points to the first element of an array
for (i = 0; i < 10; i++) //prints the values
{
printf("%d\n", *ptr);
ptr ++;
}
I understood the difference in accessing the values in both cases. However I didnot understand what is the advantage of using the first case i.e. pointer to an array of 10 integers even if the second case looks simple.
解决方案
In your particular example
int arr[10]
int (*ptr)[10];
ptr = & arr; //points to the base address of an array of 10 integers
for (i = 0; i < 10; i++) //prints the values
printf("%d\n", *(*ptr + i)); //NOTE: same as `ptr[0][i]`
there's no advantage or at least no advantage being utilized.
*(*ptr+i)
with int (*ptr)[10];
will/should generate the same assembly as
*(ptr+i)
would with int ptr[10];
(Note: some/many might find ptr[0][i]
and ptr[i]
respectively as more readable renderings of these expressions)
Example:
int get_nth(int (*X)[10], int N) { return *(*X+N); }
int get_nth_(int *X, int N) { return *(X+N); }
x86_64 output (gcc -O3 or clang -O3):
get_nth: # @get_nth
movsxd rax, esi
lea rax, [rdi + 4*rax]
ret
get_nth_: # @get_nth_
movsxd rax, esi
lea rax, [rdi + 4*rax]
ret
https://gcc.godbolt.org/z/up7HXc
If int (*ptr)[10]
were derived from a multidimensional array
as in
int multidim[5][10]; //array 10 or array 5 of int
int (*ptr)[10]=&multidim[1];
you could use the first index to jump the pointer in increments of 10*sizeof(int)
in addition to using the second one to jump in increments of sizeof(int)
(as with a plain int*
).
In a standalone example (i.e., where the 10-int block isn't part of a multidimensional array), probably the only "advantage" of int(*)[10]
is that it retains the sizeof
information (even across a function call boundary), and you could conceivably use this for explicit bounds-checking.
Bounds-checking example:
#include <stdio.h>
#define CHECKED_SUBSCRIPT(PtrArray, Index) (*(PtrArray))[BOUNDCHECK(Index,ARRCNT(*(PtrArray)))] /*{{{*/
#include <assert.h>
static inline size_t BOUNDCHECK(size_t Index, size_t Bound)
{
assert(Index < Bound);
return Index;
}
//sizeof(A) or void (=>error) if A isn't an array
#define ARRSZ(A) (+ sizeof(A) + 0* /*{{{*/\
_Generic((__typeof(&(A)[0])*)0, __typeof(__typeof(A)*):(void)0,default:0) ) /*}}}*/
#define ARRCNT(A) (ARRSZ(A)/sizeof((A)[0])) /*}}}*/
int main()
{
int arr[10]={0,2,4,6,8,10,12,14,16,18};
int (*ptr)[10] = &arr;
for (int i = 0; i < 20; i++){
printf("%d\n", CHECKED_SUBSCRIPT(ptr,i));
}
}
Output:
0
2
4
6
8
10
12
14
16
18
a.out: boundschecking.c:7: BOUNDCHECK: Assertion `Index < Bound' failed.
推荐阅读
- javascript - 在JS中循环构造函数不起作用
- mysql - 从 Azure Database for MYSQL 复制到 VM MYSQL 中的 Mysql 数据
- javascript - express mongodb查找查询结果空数组
- python - Selenuim:返回 NoSuchElementException:消息:在 Safari 上的机器人框架中使用关键字时
- java - Java :: 比较 ronded 双打不起作用
- javascript - 承诺中的内存泄漏
- python - 从两个 txt 文件中读取数据并将相关信息写入第三个 txt 文件
- c - 静态变量的初始化和赋值
- parameters - 包含文件中的 &* 参数
- jquery - 多个浏览器上的 Jquery WebSocket 流