第一次写技术类博客,不足之处还请指出


问题最先是帮学弟改程序的时候考虑到一个bug可能是数组越界的原因导致,因为我们都知道,访问二维数组中的元素时,多采用下标的方式,如a[i][j],就表示访问a数组第i行,第j列的元素。

而学弟用的是指针访问,当然本质是一样的,只是语法上稍有不同:

* ( *( a + i ) + j ) 这样同样表示访问a数组第i行,第j列的元素,但是相较于按下标访问很是麻烦,所以并不推荐,或者说应该是要避免这种写法。

但是学弟 用的是另一种方式:

*(*(a + x)) 我知道学弟想表达的是如果x大于a的行数,编译器变便会自动转向另一列,如是循环。但是真的可以这样做吗?

我自己做了一段调试的代码:

#include "iostream"

using namespace std;

int main()
{
	int a[8][8] = {};

	for(int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			cout << a[i][j] << endl;
		}
	}


	cout << *(*(a + 8)) << endl;
	cout << *(*(a + 9)) << endl;



	system("pause");
	
	return 0;
}

这段代码输出如下:

redis 二维度排序_c++

很奇怪的是不仅没有报错,而且还都有输出,* ( * ( a + 8 ) )输出了一个很大的值,而* ( * ( a + 9 ) )则输出了0,但至少有一点可以确定,那就是 不论 a + 8,还是 a + 9 都已不再是a数组中的元素指针,但是为什么会有这种情况呢?
询问大神后解释如下:

这个位置到底是不是0,这个很难确定,如果你的a[8][8]是在栈上的,那么a后面的一个地址是否清0和编译器有关,一般的编译器为了效率是不清0的,但这个不确定。因为c和c++的标准里没有强制规定一定要清0;如果a[8][8]是在堆上申请的,也就是通过new或者malloc,那么这个将更复杂,因为对new的调用会有2套逻辑,其中有一种走mmap的逻辑是会清0的,而另一种走内存池的逻辑不清0

至于为什么编译器没有报错,那是因为C/C++的编译器为了效率考虑根本不会去检查数组是否越界,完全要靠自己保证代码的正确。