V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
itfanr
V2EX  ›  C

C语言如何用指针的指针打印二维数组?

  •  
  •   itfanr · 2013-08-04 10:28:11 +08:00 · 2104 次点击
    这是一个创建于 4136 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如 :

    int a [3] [2] = {{1,2},{3,4},{5,6}} ;

    函数原型;

    void myPrint (const int **vect, int row, int col) ;

    不采用这样的原型:

    void myPrint(const int (*p)[2], int row) //当然此处row = 3 这种函数不灵活

    谢谢啦~~~~~~~~~
    30 条回复    1970-01-01 08:00:00 +08:00
    sNullp
        1
    sNullp  
       2013-08-04 10:29:50 +08:00
    NO YOU CANT
    itfanr
        2
    itfanr  
    OP
       2013-08-04 10:34:27 +08:00
    @sNullp why?
    timonwong
        3
    timonwong  
       2013-08-04 10:41:17 +08:00
    不论几维数组存储方式都是线性。
    itfanr
        4
    itfanr  
    OP
       2013-08-04 10:43:08 +08:00
    void main(){

    int a [3] [2] = {{1,2},{3,4},{5,6}} ;
    int *pa ;
    int **ppa ;
    for (int i = 0 ;i<3; i++)
    {
    for (pa = a[i]; pa - a[i]<2; pa++)
    {
    ppa = &pa ;
    printf("%d ", **ppa) ;
    }
    }

    }
    itfanr
        5
    itfanr  
    OP
       2013-08-04 10:46:24 +08:00
    @timonwong 那你说我的想法能不能用子函数实现?
    sNullp
        6
    sNullp  
       2013-08-04 11:30:53 +08:00
    @itfanr 数组名和指针不是完全一样的。。所以数组的维度不能通过别的变量来传递。但是如果是指针的指针则可以。
    felix021
        7
    felix021  
       2013-08-04 11:45:30 +08:00
    原型应该用这样,少一个星号:

    void myPrint (const int *vect, int row, int col);

    C语言里二维数组的每个元素都是连在一起的。
    icenan2
        8
    icenan2  
       2013-08-04 12:42:44 +08:00   ❤️ 1
    void myPrint (const int **vect, int row, int col)
    {
    const int *array=(const int*)vect;
    int i,j;
    for(i=0;i<row;i++)
    {
    for(j=0;j<col;j++)
    {
    printf("%d,",array[i*col+j]);
    }
    printf("\n");
    }
    }
    jesse_luo
        9
    jesse_luo  
       2013-08-04 14:20:12 +08:00
    @icenan2 强转回来了哈哈……
    leavic
        10
    leavic  
       2013-08-04 15:28:52 +08:00
    二维数组在内存中也是连续的吧
    itfanr
        11
    itfanr  
    OP
       2013-08-04 18:33:13 +08:00
    @icenan2 mark 改天我试试啊
    xdeng
        12
    xdeng  
       2013-08-04 18:57:52 +08:00 via iPhone
    指针。 没有什么 做不到
    jiych
        13
    jiych  
       2013-08-05 10:16:51 +08:00
    找到地址,就找到了指针。
    int
    main(int argc, char **argv)
    {
    int a [3] [2] = {{1,2},{3,4},{5,6}} ;
    int i,j;

    dir = getenv("PWD");
    printf("dir:%s\n", dir);

    for(i=0;i<3;i++)
    for(j=0;j<2;j++)
    printf("%p ", &a[i][j] );
    printf("\n");

    myPrint((const int **)a, 3, 2);
    exit(EXIT_SUCCESS);
    }

    void myPrint (const int **vect, int row, int col)
    {
    int i;
    int j;

    printf("in myPrint\n");
    for(i=0;i<row*col;i++)
    printf("%p ", vect+i);
    printf("\n");
    }
    jiych
        14
    jiych  
       2013-08-05 10:17:56 +08:00
    @jiych
    上面代码
    dir = getenv("PWD");
    printf("dir:%s\n", dir);
    是多余的
    pright
        15
    pright  
       2013-08-05 11:52:08 +08:00
    用gcc的话可以用变长数组,不过不推荐
    void myPrint(const int **vect, int row, int col)
    {
    int i, j;
    int (*array)[col] = (int (*)[col])vect;

    for (i=0; i<row; ++i)
    {
    for (j=0; j<col; ++j)
    {
    printf("%d ", array[i][j]);
    }
    }
    }
    itfanr
        16
    itfanr  
    OP
       2013-08-05 16:36:12 +08:00
    @pright 变长数组?vc好像不支持吧?至少为const
    pright
        17
    pright  
       2013-08-05 22:57:23 +08:00
    @itfanr 很久不用vc了,没印象了,支持c99的话就有
    pright
        18
    pright  
       2013-08-05 23:04:18 +08:00
    @jiych 这种方式在64位机器就不对了
    Gal3rielol
        19
    Gal3rielol  
       2013-08-06 00:48:37 +08:00
    凡是用双重指针传参的全部都是错的
    一维数组的类型int []可以视为为 int *
    二维数组里面的数据元素的类型并不是int *;

    我把代码贴上来
    #include <stdio.h>

    void pretty_print(int *start, int row, int col)
    {
    for (int i = 0; i < row; ++i) {
    for (int j = 0; j < col; ++j) {
    int *address = start + i * col + j; //手动计算地址
    printf("%d ", *address);
    }
    printf("\n");
    }
    return;
    }

    int main(int argc, const char **argv)
    {
    int a[3][2] = {{1, 2}, {3, 4}, {5, 6}};
    pretty_print((&a[0][0]), 3, 2);

    int **p;
    *p = &a[0]; //编译器会报类型不匹配的Warning

    return 0;
    }

    2维数组在内存中也是线性的布局, 正确的做法是拿到第一个元素的地址手动计算剩下元素的地址.

    clang报的warning如下
    warning: incompatible pointer types assigning to 'int *' from
    'int (*)[2]' [-Wincompatible-pointer-types]
    *p = &a[0];
    ^ ~~~~~
    可以看到 *p的类型是int *, 而
    pright
        20
    pright  
       2013-08-06 11:58:15 +08:00
    所以要强转啊
    xiaoye5200
        21
    xiaoye5200  
       2013-08-06 14:08:07 +08:00
    void myPrint(const int *vect, int len)
    {
    int i=0;
    for(;i<len;i++)
    printf("%d",*vect++);
    }

    int main()
    {
    int a [3] [2] = {{1,2},{3,4},{5,6}} ;
    myPrint(&a[0][0],sizeof(a)/sizeof(int));
    }

    为什么都喜欢用双重循环呢
    itfanr
        22
    itfanr  
    OP
       2013-08-06 16:12:01 +08:00
    @xiaoye5200 指针的指针呢
    jiych
        23
    jiych  
       2013-08-06 17:31:53 +08:00
    @pright 是的,多谢提醒
    printf("%p ", vect+i);改为 printf("%p ", (const int*)vect+i);就可以了
    xiaoye5200
        24
    xiaoye5200  
       2013-08-06 18:24:32 +08:00
    @itfanr 关键没必要用指针的指针
    Gal3rielol
        25
    Gal3rielol  
       2013-08-07 00:01:57 +08:00
    @xiaoye5200 指针的指针是错误的, 不是没必要而是错误的.
    xiaoye5200
        26
    xiaoye5200  
       2013-08-07 02:33:46 +08:00
    @Gal3rielol

    1,lz要的其实是如下代码。
    2,指针的指针当然不是错的。

    #include <stdio.h>

    void myPrint (int **vect, int row, int col)
    {
    int (*p)[2]=(int(*)[2]) vect;
    for (int i=0; i<row; i++)
    for (int j=0; j<col; j++)
    printf("%d\n",p[i][j]);
    }


    int main(int argc, const char * argv[])
    {
    int a [3] [2] = {{1,2},{3,4},{5,6}} ;
    myPrint((int**)a, 3, 2);
    return 0;
    }
    itfanr
        27
    itfanr  
    OP
       2013-08-07 10:30:20 +08:00
    @xiaoye5200 额 不是有没有必要 我只是有个疑惑,大家帮忙而已啊
    Gal3rielol
        28
    Gal3rielol  
       2013-08-07 10:48:29 +08:00
    @xiaoye5200 既然你说指针的指针是对的又为什么要强转呢?
    pright
        29
    pright  
       2013-08-07 14:10:55 +08:00
    @itfanr 因为标准是这样的,某类型的数组只会转换为该类型的指针,对应二维数组只会转换为一维数组指针,int[3][2]->int(*)[2]。所以要么按内存排布自己处理,要么强转回原始类型
    729 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type “array of type” is converted to an expression with type “pointer to type” that points to the initial element of the array object and is not an lvalue.
    http://c0x.coding-guidelines.com/6.3.2.1.html
    itfanr
        30
    itfanr  
    OP
       2013-08-07 21:22:14 +08:00
    @pright 你说的非常对 嗯嗯
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2575 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:28 · PVG 23:28 · LAX 07:28 · JFK 10:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.