常规静态分配数组如下所示,可以使用以下公式进行访问:

const int N = 3;
const int M = 3;

int a1[N][M] = { {0,1,2}, {3,4,5}, {6,7,8} };

int x = a1[1][2]; // x = 5 
int y = *(a1+2+N*1); // y = 5, this is what [] operator is doing in the background

数组是连续的内存区域.在动态数组分配的情况下看起来有所不同,而是有指向数组的指针数组:

int** a2 = new int*[N];
for (int i = 0; i < N; i++) 
   a2[i] = new int[M];

//Assignment of values as in previous example

int x = a2[1][2];
int y = *(*(a2+1))+2); // This is what [] operator is doing in the background, it needs to dereference pointers twice

如我们所见,[]运算符执行的操作与典型的连续数组和动态分配数组完全不同.

  1. 我对[]操作的理解正确吗?
  2. C/C++编译器如何区分它应该执行哪个[]操作,以及在哪里实现?我可以通过重载[]操作符在C++中实现它,但是C/C++如何处理这个问题呢?
  3. 在C语言中使用malloc而不是new,它能正常工作吗?我看不出有什么理由不这样做.

推荐答案

对于数组的这个声明

int a1[N][M] = { {0,1,2}, {3,4,5}, {6,7,8} };

这些记录

int x = a1[1][2];
int y = *(a1+2+N*1); 

两者并不等同.

第二个是不正确的.表达式*(a1+2+N*1)的类型int[3]隐式转换为用作初始值设定项的类型int *的对象.因此,整数变量y由指针初始化.

运算符a1[1]的计算结果为*( a1 + 1 ).结果是int[3]型的一维array.

所以应用第二个下标操作符,你会得到*( *( a1 + 1 ) + 2 ).

当使用二维数组和动态分配数组时,表达式之间的区别在于,该表达式(a1 + 1)中的二维数组的指示符被隐式转换为指向其类型int ( * )[3]的第一个元素的指针,而指向动态分配的指针数组的指针仍然具有相同的类型int **.

在第一种情况下,取消对表达式*(a1 + 1 )的引用将得到int[3]类型的左值,而在表达式*( a1 + 1) + 2中使用的int[3]类型又被隐式转换为int *类型的指针.

在第二种情况下,表达式*(a1 + 1)生成int *类型的对象.

在这两种情况下,都使用指针算法.不同之处在于,在下标运算符中使用数组时,它们会隐式转换为指向第一个元素的指针.

当您已经处理指向数组第一个元素的指针时,动态分配array.

例如,而不是这些分配

int** a2 = new int*[N];
for (int i = 0; i < N; i++) 
   a2[i] = new int[M];

你可以直接写

int ( *a2 )[M] = new int[N][M];

C++相关问答推荐

GCC不警告隐式指针到整数转换'

编译SDL 2时缺少SDL_ttf

如何解决C中的严格别名?

C由四个8位整数组成无符号32位整数

将数据移动到寄存器时出现分段故障

GCC创建应用于移动项的单独位掩码的目的是什么?

Sizeof(&Q;字符串&Q;)的正确输出是什么?

在C中访问数组中的特定值

如何只获取字符串的第一个单词,然后将其与c中的另一个单词进行比较?

使用nmake for程序比Hello World稍微复杂一些

不确定如何处理此编译错误

用C++高效解析HTTP请求的方法

当我将偏移量更改为任何非零值时,C中的mmap共享内存出现无效参数错误

Makefile无法将代码刷新到ATmega328p

未使用sem_open正确初始化信号量

C程序printf在getchar while循环后不工作

I';我试着从.txt文件中读取文本,并用c计算其中的单词数量

在哪里可以找到叮当返回码的含义?

即使客户端不发送数据,也会发生UNIX套接字读取

在链表中插入一个值