二维数组用以指针为参数的函数输出问题(尝试运用了二级指针)

问题遇到的现象和发生背景

二维数组用指针输出时的结果出现问题
我用了两个函数尝试对比输出的差别

问题相关代码,请勿粘贴截图
#include<stdio.h>
void printArr1(int *arr,int len,int width);
void printArr2(int **arr,int len,int width);
int main()
{
int b[3][2]={
        {3,2},
        {1,4},
        {4,5},
    };
    printArr1((int *)b,3,2);
    printf("\n");
    printArr2((int**)b,3,2);
return 0;
}
//函数定义
void printArr1(int * arr,int len,int width){                        
    for (int i = 0; i<len; i++) {
        for (int j = 0; j<width; j++) {
            
            printf("%d \n",*((int*)arr+i*width+j)); //输出正确
            //printf("%d \n",*(arr+i*width+j));       //输出正确
        }
    }
}
void printArr2(int ** arr,int len,int width){                        
    for (int i = 0; i<len; i++) {
        for (int j = 0; j<width; j++) {

            //printf("%d \n",*((int*)arr+i*width+j)); //输出正确
            printf("%d \n",*(arr+i*width+j));//输出错误
        }
    }
}
运行结果及报错内容

正确输出的顺序为3 2 1 4 4 5
错误输出的为3 1 4 16 很大的数 很大的数

我的问题

printf中的(int *)是强制类型转换吗?

(int*)在这的作用是什么?    为什么有它和没它会有差别?

为什么第一个函数的两种输出方式都正确而第二个函数的第二种却输出错误了呢?应该怎么改?
这两个函数中的指针有什么区别?怎么理解?


我不知道你有听说过没,二维数组可以分成n个一维数组,n是行的个数。而每个一维数组的首地址也就是*(a+i).在这里*可不是指针啊,是取地址符号。所以我么可以知道(int *),他的目的,你可以理解成强制转换,但实际作用是为了取每个一维数组的地址。

我不知道你有听说过没,二维数组可以分成n个一维数组,n是行的个数。而每个一维数组的首地址也就是*(a+i).在这里*可不是指针啊,是取地址符号。所以我么可以知道(int *),他的目的,你可以理解成强制转换,但实际作用是为了取每个一维数组的地址。
http://t.csdn.cn/XtSss
自己昨天做的文章,有这方面的