二维数组和二级指针(真的没什么关系)

刚开始学c语言的时候,总是会认为,一级指针可以用来访问一维数组,那么二维数组就要用二级指针来访问啦。。。。

实际上二级指针和二维数组真的没什么关系,而且,切记千万不要用二级指针访问二维数组。。。。。

下面是几个有关的小程序,加深印象。。。。。。。。

实验环境:主机CPU酷睿i5,vs2012

程序1:

int _tmain(int argc, _TCHAR* argv[])
{
    int **p= NULL;
    int a[2][3] = {1,2,3,4};
    p = a;
    return 0;
}

结果:编译错误,错误提示:无法从“int [2][3]”转换为“int **

可见,二级指针和二维数组名,根本就不是一类东西。

程序2:

int _tmain(int argc, _TCHAR* argv[])
{
    int **p= NULL;
    int a[2][3] = {1,2,3,4};
    p = (int **)a;
    printf("指针的长度为:%d\n",sizeof(p));
    printf("值为:%d\n",(int)(*p));
    p++;
    printf("值为:%d\n",(int)(*p));
    getchar();
    return 0;
}

输出结果:

为啥可以输出结果呢:纯属巧合!!!!!

什么巧合呢:在我的机器上指针的长度和int类型的长度都刚好为4个字节。

把程序放在虚拟机中跑一下,虚拟机的系统是CentOS7,64位的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a[2][2]={1,2,3,4};

    int **p =(int **)a;
    printf("值为:%d\n",(int)(*p));
    p++;
    printf("值为:%d\n",(int)(*p));

    char *pointer;
    printf("指针的长度为:%zd\n",sizeof(pointer));

    return 0;
}

结果:编译错误,提示:

原因是,在我的虚拟机中指针占8个字节吗,而int占四个字节。

但是long是占8个字节,所以改成long也可以实现主机中的效果。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    long a[2][2]={1,2,3,4};

    long **p =(long **)a;
    printf("值为:%ld\n",(long)(*p));
    p++;
    printf("值为:%ld\n",(long)(*p));

    char *pointer;
    printf("指针的长度为:%zd\n",sizeof(pointer));

    return 0;
}

结果为:

原因和第一个程序一样,纯属巧合:在我的虚拟机中指针和long都占8个字节。

在写这个程序的时候还有个小插曲(小错误),也设计了两个知识点,顺便分享一下,写上面程序的时候。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a[2][2]={1,2,3,4};

    int **p =(int **)a;
    printf("值为:%d\n",(long)(*p));
    p++;
    printf("值为:%d\n",(long)(*p));

    char *pointer;
    printf("指针的长度为:%zd\n",sizeof(pointer));

    return 0;
}

输出结果为:

在输出long型数据的时候我不小心用了%d,而不是%ld。

看一下用%ld的效果:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a[2][2]={1,2,3,4};

    int **p =(int **)a;
    printf("值为:%ld\n",(long)(*p));
    p++;
    printf("值为:%ld\n",(long)(*p));

    char *pointer;
    printf("指针的长度为:%zd\n",sizeof(pointer));

    return 0;
}

输出结果为:

为什么会这样?  还是要从内存角度看:

在我的虚拟机中,指针占8个字节,而p是个二级指针,*p就是个int类型的指针,占8个字节,所以其实*p占据了a[0]和a[1]。

至于为什么结果是8589934593.这还要涉及一个字节序的问题(这里就不解释了)

我的cpu是英特尔的,一般x86系列的cpu都是采用低字节序。

所以a[0]和a[1]两个单元在内存中类似于:

高地址------------------------------------------------------------------------------------低地址

00000000  00000000  00000000 00000010     00000000 00000000 00000000 00000001

把这段内存解释成long类型的数据就是8589934593

------------------------------------------------------------------------------------------------------------------------------

还要注意的是我上面,那两个巧合之下能运行的程序,都是用*p访问的,如果用**p会报错,因为**p就是*p指向的内存空间的值,而*p指向的内存,也就是8589934593地址空间,是未知的。

总之记住,二级指针和二维数据没啥关系

问题来了,既然不能用二级指针访问二维数据,那怎样用指针访问二维数组呢?

在我之前的随笔由typedef和函数指针引起的危机  中,提到了,要声明某种类型的指针变量,只需先声明处该类型的变量,然后加上*即可(注意优先级)

那么怎样用指针访问二维数组呢?

先来回忆一下怎样用指针访问一维数组。在访问一位数组时,我们实际上声明的是一个和数组元素类型相同的指针变量,指向了数组第一个元素的地址,然后在用这个指针访问数组。

比如访问int b[3]= {1,2,3}.

b中的元素为int类型,所以我们要声明一个int类型的指针变量 如int *p ,然后将p指向b的第一个元素的地址,即p = &b[0],数组的首地址和第一个元素的地址是一样的,所以也可以用p=b;

这里需要强调的是,指针类型和数组元素的类型一致,而不是数组类型一致,比如b的类型是有三个int类型元素的数组,而b中元素是int类型,b是数组类型,而元素是int类型,是不一样的。上面之所以能够用p=b,不是说p是数组类型的指针,只是数组的首地址,和数组中第一个元素的地址一样罢了。p是个int类型的指针而不是数组类型的指针,这一点一定要记住。。。。

回到二维数组来,拿int a[2][3]= {1,2,3,4,5,6}来说, 数组a的元素为 一个含有三个int类型数据的数据,即a的元素是一个一维数组,这个数组含3个元素。。。。

那么怎样声明指向a数组中元素的指针变量呢? 在由typedef和函数指针引起的危机  提到,方法及时先声明一个该类型的变量,然后加上*即可,

a中元素为含有3个int数据的数组,定义这样一个普通变量为: int p[3],然后在变量名前面加上*即可,但是要注意运算符的优先级,因为*的优先级比[]低,所以要加括号,即int (*p)[3]。

这样再将p指向a的第一个元素的地址:p = &a[0],然后就可以用p来访问数组a啦!

给出程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a[2][3] = {1,2,3,4,5,6};
    int (*p)[3] = &a[0];
    printf("值为:%d\n",(*p)[0]);
    printf("值为:%d\n",(*p)[1]);
    printf("值为:%d\n",(*p)[2]);
    p++;
    printf("值为:%d\n",(*p)[0]);
    printf("值为:%d\n",(*p)[1]);
    printf("值为:%d\n",(*p)[2]);
    getchar();
    return 0;
}

结果为:

再来一个程序,加深一下理解

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a[2][3][4] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
    int (*p)[3][4] = &a[0];
    int i = 0;
    for(;i < 3; i++)
    {
        int j = 0;
        for(; j < 4;j++)
            printf("值为:%d\n",(*p)[i][j]);

    }
    p++;
    i = 0;
    for(;i < 3; i++)
    {
        int j = 0;
        for(; j < 4;j++)
            printf("值为:%d\n",(*p)[i][j]);

    }
    return 0;
}

运行结果:

最后,贴上一张,来自csdn的图

希望对你有帮助,有纰漏的地方还请指正,谢谢。。。。

时间: 2024-11-07 02:51:26

二维数组和二级指针(真的没什么关系)的相关文章

二维数组和二级指针作为参数传给参数的方式

  一.如果要将二维数组传给一个函数,有几种传参方式?     1).直接将二维数组传给函数.     eg:         void test(int arr[3][4]); 2).以数组指针的方式传入.     eg:         void test(int (*arr)[4]); 第一种方式很容易理解.第二方式我们来分析分析.首先将二维数组看作是一个一维数组,有三个元素,arr[0],arr[1],arr[2].每个元素中有四个元素.例如,(arr[0])[0],(arr[0])[1

二维数组和二级指针关系浅析

昨天写了关于一级指针的见解,即二级数组的用法和二级指针差不多,关于数组指针和指针数组这两个是不同的概念,这一点我们一定要清楚: 数组指针我们可以理解为指向数组的指针,就是一个指针: 指针数组则可以理解为数组里存的是指针,即每个储存空间上储存的是指针变量:这里储存了多个指针 一个数组可以这样定义 char a[3];分配了3个字节的内存 二维数组可以这样定义 char b[3][3];分配了3*3 即9个字节的内存 我们知道一维数组和一级指针的用法差不多,那么二级指针有和二级指针有什么关系呢? {

编程题:指向二维数组元素的指针变量。功能:已知二维数组a[2][3],输入输出全部元素。

#include<stdio.h> void main() { int a[2][3],i,j; int *p; /*用坐标法输入二维数组元素*/ for(i=0;i<2;i++) for(j=0;j<3;j++) scanf("%d",&a[i][j]); /*用指针法输出二维数组元素*/ p=a[0];         /*等价于p&a[0][0];*/ for(;p<a[0]+6;p++)   printf("%4d&quo

指针与一维数组和二维数组以及字符串指针数组的学习笔记

废话不多少,直接上代码,关键的东西已经注释了,看注释信息理解即可. 说明:本程序讨论了一维数组和指针的关系,谈论了二维数组和指针之间的关系,讨论了字符串数组指针数组和指针之间的关系,代码中以给出定义的方法和简单的使用,但是有些使用方法并没有列出,如果需要, 请自行加入printf调试即可. 转贴请注明出处,欢迎和我讨论,谢谢. ----------cofin_add #include <stdio.h> void fun(int m, char *((*p)[m])){ int i = 0;

二维数组与双重指针(转)

原文地址:https://blog.csdn.net/u013684730/article/details/46565577 一.简介 1.二维数组 int array[10][10];    函数声明: void fun(int a[][10])    函数调用:fun(array);   访问: 一般使用a[i][j]来访问数组中的元素 2.指针数组 int *array[10];    函数声明:void fun(int *a[10]);    函数调用:fun(array);    访问

8.31 二维数组 字符串和指针

指针+1移动了相当于所指向类型的大小的字节 int *s1[100] 移动了4个字节 int (*s2)[100] 移动了400个字节 char *s3 移动了1 个字节 int *s4 移动了4个字节 ***p2如何理解? int *p0 = &i *p0  = i int **p1 = &p0 **p1 = i int ***p2 = &p1 ***p2 = i *p2 = p1的值 **p2 = p0的值 ***p2 = i的值 所以***p2就是p0的值        而p

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

引用地址: 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");} 编译,然后就会发现通不过,报错:错

C语言笔记(二维数组与数值指针)

一.关于二维数组和二维数组区别 (1)一维数组在内存中是连续分布存储的,同样,二维数组也是在内存连续存储的.所以从内存的角度来分析,一维数组和二维数组其实没有本质区别. (2) 二维数组可以使用一维数组来代替.但是在实际的应用中,有时候使用二维数组会更加直观,方便程序的编程. (3)两者在内存使用效率上是一模一样的. 二.二维数组的第一维和第二维概念 (1)例如 int a[2][5]中,前面的2表示第一维:后面的5表示第二维 (2) 二维数组的第一维表示最外部的那一层,第一维本身也是一个数组,

C++ 二维数组(双重指针作为函数参数)

本文的学习内容参考:http://blog.csdn.net/yunyun1886358/article/details/5659851 http://blog.csdn.net/xudongdong99/article/details/6723163 1.使用二维数组作为形参的例子: void func(int arr[][10]) { } int main() { int array[10][10]; func(array); //用二维数组名作为实参,调用函数 } 上面的例子可以编译通过,