C语言数组与指针相关语句的有效性验证及原理咨询
先明确基础变量定义:
float pin[5]; float mat[2][4]; float* ptrf;
以下是对每个语句的判断和详细解析:
1. ptrf = *mat; ✅ 正确
mat作为二维数组名,本质是指向第一个一维子数组mat[0]的指针(类型为float (*)[4],即指向含4个float的数组的指针)。*mat是对该指针的解引用,得到mat[0]——第一个一维子数组的数组名。而一维数组名在表达式中会隐式转换为指向其第一个元素的指针(float*类型),正好和ptrf的类型匹配,因此赋值合法,ptrf最终指向mat[0][0]。
2. *(mat+2) = pin[2]; ❌ 错误
首先,mat只包含2个一维子数组(索引0和1),mat+2指向的是mat[2],属于数组越界访问,本身就是未定义行为。其次,*(mat+2)的类型是float[4](一维数组),而pin[2]是单个float值,类型完全不匹配;同时数组名是不可修改的左值,根本无法被赋值,因此这条语句存在多重错误。
3. *(mat[0]) = pin[0]; ✅ 正确
mat[0]是二维数组的第一个一维子数组,在表达式中会隐式转换为指向该子数组第一个元素的指针(float*类型,指向mat[0][0])。对这个指针解引用*(mat[0]),等价于直接访问mat[0][0],这是一个可修改的float类型左值,和pin[0]的类型匹配,因此赋值合法,作用是把pin[0]的值赋给mat[0][0]。
4. ptrf = mat[1]; ✅ 正确
mat[1]是二维数组的第二个一维子数组,在表达式中同样会隐式转换为指向其第一个元素的指针(float*类型,指向mat[1][0]),和ptrf的float*类型完全匹配,因此赋值合法,ptrf最终指向mat[1][0]。
核心知识点补充
二维数组和指针的本质区别要理清:
- 二维数组
T mat[N][M]是N个元素的数组,每个元素是M个T的数组,内存是连续的。 mat的类型是T (*)[M](指向M个T的数组的指针),而非T**(指针的指针),不要混淆两者的内存布局和类型。- 一维数组名在大多数表达式中会隐式转换为指向其第一个元素的指针,但
sizeof、&操作符中除外。
内容的提问来源于stack exchange,提问作者stratakos

