1. 指向指针的指针

(1)指针的本质是变量,会占用一定的内存空间

(2)可以定义指针的指针来保存指针变量的地址值

(3)指针是个变量,同样也存在传值调用与传址调用

重置动态空间的大小

#include <stdio.h>
#include <malloc.h> int reset(char**p,int size,int new_size)
{
int ret = ;
int i = ;
int len = ;
char* pt = NULL;
char* pp = *p; if((p != NULL)&&(new_size > ))
{
pt = (char*)malloc(new_size); len = (size < new_size)?size : new_size;//取较小者 //复制原内容
for(i=; i<len;i++){
*pt = *pp++;
} free(*p); //释放原空间
*p = pt; //*p指针指向新空间
}
else
{
ret = ;
} return ret;
} int main(int argc,char* argv[], char* env[])
{ char*p =(char*)malloc(); printf("%p\n", p);//重置前二维数组的内存地址 //重置大小后二维数组的内存地址
//因为重置后的内存地址可以是新的地址,所以这里
//需传入p指针的地址,以便在reset函数内部改变p,让
//p指向新的地址。
if (reset(&p, , ))
{
printf("%p\n", p);
} free(p);
return ;
}

2.二维数组与二级指针

(1)二维数组在内存中以一维的方式排布

(2)二维灵敏组中的第一维是一维数组

(3)二维数组中的第二维才是具体的值

(4)二维数组的数组名可看做常量指针

#include <stdio.h>

//以一维数组的方式来遍历二维数组
void printfArray(int a[],int size)
{
int i = ; printf("printfArray:%d\n",sizeof(a)); //退化为指针 for(i=; i<size; i++)
{
printf("%d\n",a[i]);
}
} int main(int argc,char* argv[], char* env[])
{
int a[][] = {{, , },{, , },{, , }};
int* p = &a[][];//指向a[0][0]元素 int i;
int j; for(i = ;i < ; i++)
{
for(j = ;j < ;j++)
{
printf("%d, ",*(*(a + i) + j));//以指针方式访问元素
} printf("\n");
} printf("\n"); printfArray(p,);//以一维数组的方式访问二维数组 return ;
}

3. 数组名

(1)一维数组名代表数组首元素的地址:int a[5];a 的类型为 int*

(2)二维数组名同样代表数组首元素的地址:如 int a[3][5],a 的类型为 int(*)[5]。

二维数组

含义及类型

取地址符(&)

sizeof

数组名:a

①二维数组名a指向数组首元素的地址,即第1行(a[0])的地址(注意,不是a[0][0]的地址)。因此,a被称为行指针,指向第1行元素(一维数组)的地址。这个元素的类型是int(*)[5](即一维数组)。所以a的类型为int(*)[5];a可以看作是行指针,②a + 1表示第二行的指针,a + i表示第i + 1行的指针(也是int(*)[5]类型)……

①&a表示整个二维数组的地址,所以&a + 1指向这个二维数组最后一个元素的后面。

①sizeof(a)表示整个二维数组的大小。

②sizeof(&a)为指针大小4字节。

③sizeof(*&a)等于sizeof(a)

a[i]

①a[i]的类型:如果把二维数组看作是由三个元素(一维数组)组成的数组,那么这三个一维数组的数组名分别为a[0]、a[1]、a[2]。因此,a[0]可以看作是指向第1行(一维数组)首元素(a[0][0])的地址,a[i]是指向第i + 1行(一维数组)首元素的地址,所以a[i]为int*型。

②a[i] + 1表示这行数组第2个元素的地址,即a[i] + 1是指向a[i][1]元素的地址,*(a[i] + 1)是a[i][1]元素的值。同理,a[i] + j是指向a[i][j]的地址,*(a[i] + j)是a[i][j]的值。

&a[i]表示第i + 1行这行整个一维数组的地址。因此,&a[i] + 1是指向这行数组的下一行的指针。

①sizeof(a[i]):a[i]是一个一维数组。sizeof(a[i])为这个数组的大小。

②sizeof(&a[i])为指针大小4字节。

③sizeof(*&a[i])等于sizeof(a[i])

a[i][j]

与a、a[i]类型的含义不同,a[i][j]不再是一个指针,而是元素的类型,即int型。

&a[i][j]表示这个元素的地址,即int*型

①sizeof(a[i][j]):a[i][j]表示元素的类型。

②sizeof(&a[i][j])为指针大小。

③sizeof(*&a[i][j])等于sizeof(a[i][j])

备注

①通常情况下,数组名可看作是首元素的地址,而表格中所说的数组名a、a[i]的类型是指当他们代表各自数组的首元素时的类型。

②但当对数组名取地址符(&)或sizeof时,它不能看作是首元素的地址,而代表的是整个数组。请注意表格中&和sizeof两列的分析。

#include <stdio.h>

int main(int argc,char* argv[], char* env[])
{ int a[][] = {};
int c; printf("Information for array:a[3][5]:\n");
printf("a = 0x%08X, a + 1 = 0x%08X, sizeof(a) = %d\n", a, a + , sizeof(a));
printf("&a = 0x%08X, &a + 1 = 0x%08X, sizeof(&a) = %d, sizeof(*&a) = %d\n",
&a, &a + , sizeof(&a),sizeof(*&a)); printf("\n"); //a[i]指向一个一维数组的首元素,a[i]+1指向该行第2个元素。sizeof(a[i])时不能看成首元素,而是这行整个一维数组
for(c=;c< ;c++)
{
printf("a[%d] = 0x%08X, a[%d] + 1 = 0x%08X, sizeof(a[%d]) = %d,\n",
c, a[c], c, a[c] + ,c, sizeof(a[c]));
} printf("\n"); //对a[i]进行&取地址符时,a[i]不能看作这一行的首元素,而是整个一维数组。即&a[i]表示第i+1的整个数组
//&a[i]+1表示下一行。
for(c=;c< ;c++)
{
printf("&a[%d] = 0x%08X, &a[%d] + 1 = 0x%08X, sizeof(&a[%d]) = %d, sizeof(*&a[%d]) = %d\n",
c, &a[c],c, &a[c] + ,c, sizeof(&a[c]), c, sizeof(*&a[c]));
} return ;
} /*
输出结果:
Information for array:a[3][5]:
a = 0x0023FE80, a + 1 = 0x0023FE94, sizeof(a) = 60
&a = 0x0023FE80, &a + 1 = 0x0023FEBC, sizeof(&a) = 4, sizeof(*&a) = 60 a[0] = 0x0023FE80, a[0] + 1 = 0x0023FE84, sizeof(a[0]) = 20,
a[1] = 0x0023FE94, a[1] + 1 = 0x0023FE98, sizeof(a[1]) = 20,
a[2] = 0x0023FEA8, a[2] + 1 = 0x0023FEAC, sizeof(a[2]) = 20,
a[3] = 0x0023FEBC, a[3] + 1 = 0x0023FEC0, sizeof(a[3]) = 20,
a[4] = 0x0023FED0, a[4] + 1 = 0x0023FED4, sizeof(a[4]) = 20, &a[0] = 0x0023FE80, &a[0] + 1 = 0x0023FE94, sizeof(&a[0]) = 4, sizeof(*&a[0]) = 20
&a[1] = 0x0023FE94, &a[1] + 1 = 0x0023FEA8, sizeof(&a[1]) = 4, sizeof(*&a[1]) = 20
&a[2] = 0x0023FEA8, &a[2] + 1 = 0x0023FEBC, sizeof(&a[2]) = 4, sizeof(*&a[2]) = 20
&a[3] = 0x0023FEBC, &a[3] + 1 = 0x0023FED0, sizeof(&a[3]) = 4, sizeof(*&a[3]) = 20
&a[4] = 0x0023FED0, &a[4] + 1 = 0x0023FEE4, sizeof(&a[4]) = 4, sizeof(*&a[4]) = 20
*/

(3)二维数元素的访问方式:int a[i][j];

①a[i][j]

② *(*(a + i) + j);//a + i 是第 i+1 行首元素(一维数组)的地址,即保存一个一维数的地址,*(a + i)取出当中保存的一维数组地址。

注意这也是一个地址,而*(a + i)+j 表示在这个一维数组地址基础上加 j 的偏移处,然后*(*(a + I)+ j)取出该元素出来。

动态申请二维数组

#include <stdio.h>
#include <malloc.h> int** malloc2d(int row,int col)
{
int** ret = NULL; if((row >) && (col >))
{
int* p = NULL; //先申请第一维数组,用于存放行指针
ret = (int**)malloc(row * sizeof(int*)); //再申请整个数组存储空间的大小,用于存放所有元素
p = (int*)malloc(row * col * sizeof(int)); //将数组空间分为二维
if ((ret != NULL) && (p != NULL))
{
int i=;
for(i=; i<row; i++)
{
ret[i] = p + i*col;
}
}
else
{
free(ret);
free(p); ret = NULL;
}
} return ret;
} void free2d(int** p)
{
if(*p != NULL) //p指向二维数组
{
//*p指向p[0],而这里保存的即是
//第1个元素的地址,也是整个数
//组元素空间地址。
free(*p); //释放元素所占空间
} free(p);//释放行指针所占空间
} int main()
{
int** a = malloc2d(, );
int i = ;
int j = ; for(i=; i<; i++)
{
for(j=; j<; j++)
{
printf("%d, ",a[i][j]);
}
printf("\n");
} free2d(a); return ;
}

无法将指针变量本身传递给一个函数,须传递指针的地址

#include <stdio.h>
#include <malloc.h>
#include <string.h> void GetMemory(char* p,int num)
{
//由于p是函数参数,当函数返回时,会被释放
p = (char*)malloc(num*sizeof(char));
} void GetMemoryEx(char** p,int num)
{
//p指向一个指针,将该指针的值指向新的开辟的内存空间。
*p = (char*)malloc(num * sizeof(char));
} int main()
{
char* str = NULL; /*
//错误的做法
GetMemory(str,10);//试图让str让指向新开辟的内存空间。因为须改变
//指针str的值,所以得传递指针的地址过去。否则
//在传参时,GetMemory只是复制str的值过去。即,
//将NULL复制给参数。 strcpy(str,"hello"); free(str);//free并没有起作用,内存泄漏
*/ //正确的做法
GetMemoryEx(&str,);//将str指针的地址传递到函数里,函数内部就
//可以改变str指针的值,让其指向新的地址。 strcpy(str,"hello"); free(str);//free并没有起作用,内存泄漏 return ;
}

参考资料:
www.dt4sw.com
http://www.cnblogs.com/5iedu/category/804081.html

C语言学习笔记--多维数组和多维指针的更多相关文章

  1. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  2. 吴裕雄--天生自然C++语言学习笔记:C++ 数组

    C++ 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合.数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量. 数组的声明并不是声明一个个单独的变量,比如 number0. ...

  3. C语言学习笔记之成员数组和指针

    成员数组和指针是我们c语言中一个非常重要的知识点,记得以前在大学时老师一直要我们做这类的练习了,但是最的还是忘记了,今天来恶补一下.     单看这文章的标题,你可能会觉得好像没什么意思.你先别下这个 ...

  4. C语言学习笔记之动态分配数组空间

    本文为原创文章,转载请标明出处 高级语言写多了,再拿起C语言的时候,自己已经傻了... C语言中数组大小不能为变量,即使这个变量已经被赋过值了,应该使用malloc方法进行数组空间动态分配. 如下: ...

  5. Go语言学习笔记(三)数组 & 切片 & map

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 数组 Arrays 数组是同一种数据类型的固定长度的序列. 数组是值类型,因此改变副本的值,不会改变本身的值: 当 ...

  6. 【Java学习笔记之八】java二维数组及其多维数组的内存应用拓展延伸

    多维数组声明 数据类型[][] 数组名称; 数据类型[] 数组名称[]; 数据类型数组名称[][]; 以上三种语法在声明二维数组时的功能是等价的.同理,声明三维数组时需要三对中括号,中括号的位置可以在 ...

  7. C#学习笔记(八):多维数组

    一维数组 冒泡排序 二维数组 Length:取数组元素的总个数 GetLength:取不同维度的个数 using System; using System.Collections.Generic; u ...

  8. C语言学习笔记(五) 数组

    数组 数组的出现就是为了解决大量同类型数据的存储和使用的问题: 数组的分类:一维数组.二维数组. 一维数组:为多个变量连续分配存储控件:所有的变量的数据类型必须相同:所有变量所占的字节大小必须相等: ...

  9. 【Java学习笔记之九】java二维数组及其多维数组的内存应用拓展延伸

    多维数组声明 数据类型[][] 数组名称; 数据类型[] 数组名称[]; 数据类型数组名称[][]; 以上三种语法在声明二维数组时的功能是等价的.同理,声明三维数组时需要三对中括号,中括号的位置可以在 ...

随机推荐

  1. dom 兼容性问题 2 offset

        offsetParent : 离当前节点最近的具有定位属性的祖先节点. 如果所有祖先节点都没有定位属性: 对于一个有定位属性的元素: ie6.7 : offsetParent 是 html 节 ...

  2. MVC3 学习总结一(未发布)

    MVC:  Model,View,Control   设置View中的数据 1. 返回model,View中强类型化 Control: public ActionResult Browse(strin ...

  3. Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions

    Model compatibility cannot be checked because the database does not contain model metadata. Ensure t ...

  4. c++中对齐方式

    使用cout<<setiosflags(ios::right)以后, 再调用 cout<<setiosflags(ios::left);无效的, 你可以在调用之前加上一句 co ...

  5. 2018.8.10 programming bat based on python

    @echo off REM Current DevProg Version. Match the pip package version (x.y.z)SET currentversion=0.4.0 ...

  6. OpenCV - win7+vs2013(2012)+opencv3.0.0 环境配置 (以及配置技巧)

    1. opencv 3.0.0 库下载地址, 这里的版本是3.0.0,其他的版本配置可能不一样,请大家注意. http://sourceforge.net/projects/opencvlibrary ...

  7. Python 中的几种矩阵乘法 np.dot, np.multiply, *

    使用array时,运算符 * 用于计算数量积(点乘),函数 dot() 用于计算矢量积(叉乘).使用matrix时,运算符 * 用于计算矢量积,函数 multiply() 用于计算数量积. 下面是使用 ...

  8. [Luogu3852][TJOI2007]小朋友

    luogu 题意 求弦图的最大独立集. sol 按照完美消除序列一个个贪心选即可. code #include<cstdio> #include<algorithm> #inc ...

  9. LeetCode 305. Number of Islands II

    原题链接在这里:https://leetcode.com/problems/number-of-islands-ii/ 题目: A 2d grid map of m rows and n column ...

  10. 高并发下Redis如何保持数据一致性(避免读后写)

    通常意义上我们说读后写是指针对同一个数据的先读后写,且写入的值依赖于读取的值. 关于这个定义要拆成两部分来看,一:同一个数据:二:写依赖于读.(记住这个拆分,后续会用到,记为定义一.定义二)只有当这两 ...