函数中的二维数组和二级指针

    科技2024-04-19  6

    二维数组和二级指针

    被指针逼疯了才想出如此歪门邪道去理解它,文章错误之处还请大家私聊或者在评论区告诉我

    下面函数调用时,二维数组a必须用类型强转才能实现对int** a的参数传递 说明二维数组和二级指针依然有明显的区别,我们用打印地址的方法来探究它们的区别(注:二维数组名是个指针)

    #include <iostream> using namespace std; void func(int **a) { cout <<"传递之后a: "<< a<<endl; cout <<"传递之后a+1:"<< a + 1 << endl; } int main() { int a[3][3] = { 0,1,2,3,4,5,6,7,8 }; func((int **)a);//强制类型转换 cout <<"传递之前a: "<< a<<endl; cout <<"传递之前a+1:"<< a + 1<<endl; }

    c++对函数形参实参之间匹配要求很严格,必须做到一一对应,如果不强制类型转换(int **)a,编译器就会报错,这也证明二维数组和二级指针存在着很明显的区别 输出结果为

    在16进制运算下传递之后的a之间相差8,而传递之前的a之间相差了12

    笔者的机器中,指针占8个字节,这就说明传递之后的a是个普通指针 而int类型占4个字节,12除以4为3,正好是二维数组a[3][3]中列的个数,说明a依旧和数组有关系(也是个指针,因为数组名就是个指针)

    这里说个自己总结的指针和数字相加的理解方式 c和c++中不同数据之间要想进行运算(加减乘除)必须先进行类型转换,而在上面每一个的加法运算中,都有一次“隐式”类型转换,把字面常量1转换成了表达式中a的类型,传递之前的a是数组类型的指针,所以1换成对应的类型(占12个字节),同理传递之后的a为普通指针,1就换成对应的类型(占8个字节),这样子就好理解为什么同样是指针+1,为何差值就不相同呢

    那么问题来了,函数参数传递成功之后,我能在函数中用a[][]访问数组中的元素吗

    肯定不能,因为传递之后a的本质已经变了,从上面来看,常量1都被换成不同的类型了,a肯定也变了,他已经和数组没直接关系了 那要想访问a中的元素也不是不可以,只要搞明白指针就行了,反正数据都存在内存里,也跑不了

    #include <iostream> using namespace std; void func(int **a) { cout << a<<endl; cout << (int*)a << endl; cout << *((int*)a)<<endl; cout << *(int*)(a + 1) << endl; cout << *(int*)(a + 2) << endl; } int main() { int a[3][3] = { 0,1,2,3,4,5,6,7,8 }; func((int **)a); }

    结果为:

    在函数中又进行了一次强制类型转换把a转换成了int*类型,你可以这样理解,我们为了把数组传入函数中进行了强制类型转换转成了(int **),那我们要在函数中使用这个数组就要把它的类型再转回来,而二维数组可以用int (*a)[]来表示,所以我们把它强制转换为(int *)的类型,这样我们就可以把他当成二维指针使用了(类型转换不改变指针所指的地址) 但使用上还是要有所注意的,拿cout << *(int*)(a+1) << endl;举例子:括号中的a+1,因为a是普通指针(和数组无关了),所以加1时,指针加了8个字节,而不是12,所以不能完成一次跨行的行为,这就导致输出为2(int为4占字节,8个字节相当于2个int,从0跨越到2),而不是第二行开头的3 可以借助图片理解(图中每列的地址相同)0,1,2,3,4,5之间地址相差4个字节,函数中的int**a的地址和第一列相同 这样就好理解了,如果我们想一一访问数组里的元素的话只需让a先进行强制转注意转换成int*,(这个int*可以看成一个int(*)[1]所以它+1只会跳过4个字节,变成下一个int)然后再和常量相加,再执行解引用操作

    #include <iostream> using namespace std; void func(int **a) { cout << a<<endl; cout << (int*)a << endl; cout << *((int*)a + 1) << endl; cout << *((int*)a + 2) << endl; cout << *((int*)a + 3) << endl; } int main() { int a[3][3] = { 0,1,2,3,4,5,6,7,8 }; func((int **)a); }

    输出结果为

    Processed: 0.038, SQL: 9