二维数组和指向指针的指针

转自

http://www.cnblogs.com/stoneJin/archive/2011/09/21/2184211.html

一道面试题引发的问题,首先要知道[]的优先级高于*,题目:

char **p,a[6][8]; 问p=a是否会导致程序在以后出现问题?为什么?

直接用程序说明:

#include<stdio.h>

void main()
{
    char **p,a[6][8];
    p = a;
    printf("\n");
}


编译,然后就会发现通不过,报错:错误 1 error C2440: “=”: 无法从“char [6][8]”转换为“char **” 

于是乎,我看了下《C专家编程》里10.5节—使用指针向函数传递一个多维数组。

方法一,函数是 void fun(int arr[2][3]); 这种方法只能处理2行3列的int型数组。

方法二,可以省略第一维的长度。函数是 void fun(int arr[][3]);这种方式虽然限制宽松了一些,但是还是只能处理每行是3个整数长度的数组。

    或者写成这种形式 void fun(int (*arr)[3]);这是一个数组指针或者叫行指针,arr和*先结合使得arr成为一个指针,这个指针指向具有3个

    int类型数据的数组。

方法三,创建一个一维数组,数组中的元素是指向其他东西的指针,也即二级指针。函数是 int fun(int **arr);这种方法可以动态处理各行各列不一样长度的数据。

注意:只有把二维数组改成一个指向向量的指针数组的前提下才可以这么做!比如下面的程序可以正常输出abc:

#include <iostream>
using namespace std;
void test(char **ptr)
{
    cout << *ptr << endl;
}
 
int main()
{
    char *p[3] = {"abc", "def", "ghi"};
    test(p);
    return 0;
}


数组和指针参数是如何被编译器修改的?

数组名被改写成一个指针参数”规则并不是递归定义的。数组的数组会被改写成“数组的指针”,而不是“指针的指针”:

实参                                                      所匹配的形参

数组的数组          char c[8][10];                 char (*)[10];          数组指针

指针数组             char *c[10];                   char **c;               指针的指针

数组指针(行指针)  char (*c)[10];                 char (*c)[10];        不改变

指针的指针           char **c;                       char **c;               不改变

下面再看一个网友的一段分析相当给力的代码:

复制代码
#include "stdafx.h" 
#include <iostream> 
using namespace std; 
 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int arr1[3]; 
    int arr2[3]; 
    int arr3[3]; 
    int * ptr; 
    // ptr1是一个指向 int [3] 的指针,即ptr的类型和&arr1的类型是一样的,注意:arr1指向的内存区域定长 
    int ptr1[3][3]={{1,2,3},{1,2,3},{1,2,3}}; 
    // ptr2是一个指向 int * 的指针,即ptr2的类型和&ptr是一样的,注意:ptr指向的内存区域不定长 
    int * ptr2[3]={arr1,arr2,arr3}; 
    // ptr3是一个指向 int [3] 的指针,即ptr3的类型和&arr1的类型是一样的,注意:arr1指向的内存区域定长 
    int(* ptr3)[3]=&arr1; 
    ptr3=ptr1; // 没错,他们的类型相同 
 // ptr3=ptr2;//error 无法从“int *[3]”转换为“int (*)[3] 
 // ptr4是一个指向 int * 的指针,即ptr4的类型和&ptr是一样的,注意:ptr指向的内存区域不定长 
    int ** ptr4; 
    //ptr4=&arr1; //error 无法从“int (*)[3]”转换为“int ** 
    ptr4=ptr2; // 没错,他们的类型相同 
 //ptr4=ptr3; // error 无法从“int (*)[3]”转换为“int ** 
    return 0; 
}
复制代码

### 二维数组指针指针数组的区别及使用方法 #### 一、概念区分 1. **二维数组指针** 二维数组指针是一个指向二维数组的指针,其定义形式为 `int (*p)[N]`,其中 `N` 表示二维数组中每行的元素个数。这种指针可以用来直接访问整个二维数组,或者逐行访问数组的内容[^1]。 2. **指针数组** 指针数组是一个数组,其中每个元素都是一个指针。其定义形式为 `int *p[M]`,其中 `M` 表示数组的长度。指针数组中的每个元素可以指向不同的内存地址,通常用于存储多个字符串或动态分配的数组[^1]。 #### 二、定义方式 1. **二维数组指针的定义** 定义一个二维数组指针时,需要明确二维数组的列数。例如: ```c int arr[3][4] = {{1, 3, 5, 7}, {2, 4, 6, 8}, {11, 22, 33, 44}}; int (*p)[4]; // 定义一个指向包含4列的二维数组的指针 p = arr; // 将指针指向二维数组 ``` 2. **指针数组的定义** 定义一个指针数组时,不需要指定列数,而是指定数组中指针的数量。例如: ```c int a = 10, b = 20, c = 30; int *p1[3]; // 定义一个包含3个指针的指针数组 p1[0] = &a; p1[1] = &b; p1[2] = &c; ``` #### 三、操作方式 1. **二维数组指针的操作** - 通过二维数组指针访问数组元素时,可以直接使用 `(*p)[j]` 或 `p[i][j]` 的形式。 - 示例代码: ```c #include <stdio.h> int main() { int arr[3][4] = {{1, 3, 5, 7}, {2, 4, 6, 8}, {11, 22, 33, 44}}; int (*p)[4]; // 定义一个指向包含4列的二维数组的指针 p = arr; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("%d ", p[i][j]); // 访问二维数组元素 } printf("\n"); } return 0; } ``` 上述代码中,`p[i][j]` 等价于 `(*(p + i))[j]`,表示访问第 `i` 行第 `j` 列的元素[^2]。 2. **指针数组的操作** - 指针数组中的每个元素可以独立指向不同的地址。 - 示例代码: ```c #include <stdio.h> int main() { int a = 10, b = 20, c = 30; int *p1[3]; // 定义一个包含3个指针的指针数组 p1[0] = &a; p1[1] = &b; p1[2] = &c; for (int i = 0; i < 3; i++) { printf("%d ", *p1[i]); // 解引用指针数组中的指针 } return 0; } ``` 在上述代码中,`*p1[i]` 表示解引用指针数组中的第 `i` 个指针,获取其所指向的值[^3]。 #### 四、注意事项 1. 二维数组指针在定义时必须明确列数,因为编译器需要知道每一行的大小以便正确计算偏移量。 2. 指针数组中的每个指针可以指向不同的地址,但它们本身是连续存储的。 3. 当通过指针访问二维数组时,`p + 1` 表示指向下一整行的地址,而 `*p + 1` 表示指向同一行的下一个元素[^3]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值