程序片段(01):01.指针数组.c+02.动态数组.c

内容概要:指针数组

///01.指针数组.c
#include <stdio.h>
#include <stdlib.h> //01.指针数组作为函数的形参:
// 会退化为一个二级指针!
//02.如何确定一个数组作为函数形参将会退化为什么样儿的指针?
// 关键在于形参数组当中的元素是什么类型!就是什么类型的指针
void show01(char * str[5])//char *str[5]
{
for (int i = 0; i < 5; ++i)
{
printf("%s \n", str[i]);//char **str
}
} //03.等价关系:
// 二级指针和指针数组的数组名所对应的解析方式都一样!
void show02(char ** str)
{//指针数组作为函数的形参进行传参的时候,指针数组的数组名将会退化为一个二级指针!
for (int i = 0; i < 5; ++i)
{
printf("%s \n", str[i]);
}
} //04.函数形参的拦截机制:
// 如果是数组,就没有副本机制,不是副本,就有拦截介质
//注:解除数组的副本机制依赖于数组名的退化机制!
//05.如何确定一个变量的数据类型?
// 在定义变量的基础情况之下,挖掉变量名,就是变量的数据类型
//注:字符指针数组开发过程当中比较常用!
int main01(void)
{
int * arr[10];//-->int * [10]-->一级指针数组类型!
//一级指针数组的数组名arr在作为函数形参的时候,该一级指针的数组名会自动退化以为一个二级指针
char * str[5] = { "calc", "notepad", "tasklist", "mspaint", "pause" };
//char * [N]:字符指针类型的一级指针数组在开发过程当中经常使用!
char **pp = str;//变量指针=常量指针(地址意义的数组赋值动作!)-->指针变量结果-->指针变量遍历!
printf("%p \n", str);//二级指针常量的数值
//show01(str); <= = > show02(str); system("pause");
}
///02.动态数组.c
#include <stdio.h>
#include <stdlib.h> //01.如何确定动态数组的数组名称?
// 1.开辟内存的时候所采用的指针变量名称就是动态数组名称!
// 2.通过指针变量名称的访问方式就如同标准数组的访问方式!
// 注:严格区分变量指针和常量指针之间的差别!
int main02(void)
{
//动态分配一个一维数组
int * const arr = malloc(30 * sizeof(int));
for (int i = 0; i < 30; ++i)
{
printf("%d \n", arr[i] = i);//arr[i]<=>*(arr+i)
} system("pause");
} //02.动态数组的分配要点:
// 1.动态内存开辟函数!
// 2.解析动态内存的指针类型!
// 注:所有数组都看做为一维数组!,指向该数组首元素的指针
// 指针可以使用:变量指针和常量指针(模拟栈内存数组!)
// 注:动态数组的尺寸在程序运行过程当中决定!
// 每个当前维度的数组都必须要求明确其维度-1的特点
int main03(void)
{
//动态分配一个二维数组
//int test = 5;
int(*p)[5] = malloc(30 * sizeof(int));
for (int i = 0, num = 0; i < 30; ++i, ++num)
{
printf("%3d", p[i / 5][i % 5] = num);//0->1->2->3...
if (0 == (i + 1) % 5)
putchar('\n');
} system("pause");
} //03.两种区别的数组:
// 二维数组:数组当中的每个相邻数组元素的内存地址必须连续
// (连续!+对齐!)
// 分块数组:针对于同一个数组当中的每个数组元素的内存地址必须连续
// 但是内部就整体而言的数组元素之间是可以不连续的
// (不连续+不对齐!)
// 注:动态内存开辟函数的返回值类型为("void *")类型,只是负责返回一个有效
// 地址,但是没有具备解析意义+堆内存动态开辟函数前面的赋值号只是用于
// 返回一个明确的地址而已!-->指针类型决定对动态内存的实际解析意义!
int main04(void)
{
//使用malloc函数在堆内存当中开辟一个指针数组!
int **pp = malloc(5 * sizeof(int *));//20个堆内存字节
int num = 0;
for (int i = 0; i < 5; ++i)
{
pp[i] = (int *)malloc((5 + i)*sizeof(int));
for (int j = 0; j < 5 + i; ++j)
{
pp[i][j] = num++;//赋值
}
}
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5 + i; ++j)
{
printf("%3d", pp[i][j]);
}
printf("\n");
} system("pause");
} //04.常见数据结构的特点:
// 数组:查找效率高+增加|删除效率低
// 链表:增加|删除效率高+查找效率低
// 分块:查找效率和数组一样+增加|删除效率比数组高(略低于链表,不过可以忽略!)
// 可以不用连续,可以不用对齐!
//05.如何分配一个N-1级指针数组?
// 需要一个N级的指针!
// N级指针,存储N-1级指针数组的地址
// N级指针分配一个数组,用于存放N-1级指针数组的首个元素的地址(区分变量指针|常量指针)
// 数据等同于0级指针

程序片段(02):01.Array.c

内容概要:数组的三种形态

#include <stdio.h>
#include <stdlib.h> //01.C语言版本标准:
// 第一版:C89
// 第二版:C99
//02.(VC2013以上+GCC4.7以上)支持C99语法
// VC2013+GCC4.7
//03.C99新语法分配数组模式!
// 1.位于栈内存的静态数组
// 2.可以进行指明初始化!
// 指明初始化的最大索引可以推导数组总元素个数
// 3.指明初始化方式的特点:可以明确长度!
// 纯大括号初始化:只能同时指明数组长度,并且给数组最后一个元素初始化赋值
// 其余数组元素统统采用默认初始化方式!
// 非纯大括号初始化:可以同时指明数组长度,并且给多个数组元素初始化赋值
// 其余数组元素统统采用默认初始化方式!
int main01(void)
{
int arr[] = { [10] = 10 };//默认不操作的数组元素被赋值为0,[10]-->arr[10]=0->11个元素
for (int i = 0; i < 11; ++i)
{
printf("%d \n", arr[i]);
} system("pause");
} int main02(void)
{
int n = 4;
int * pC99 = (int[]) { [2] = 1, [4] = 10 };//静态数组
//默认不指明初始化的数组元素所对应的值为0
for (int i = 0; i < 5; ++i)
{
printf("%d \n", pC99[i]);
} system("pause");
} //04.静态数组与动态数组:
// 静态数组:
// 1.存储于栈内存
// 2.编译时期决定数组元素个数
// 3.(自动开辟+自动回收)
// 动态数组:
// 1.存储于堆内存
// 2.运行时期决定数组元素个数
// 3.(手动开辟+手动释放)
// 注:严格区分(分配+释放)以及(开辟+回收)的区别
// 分配+释放:权限
// 开辟+回收:内存
void run()
{
//int arr[5] = { 1, 2, 3, 4, 5 };
int * p = malloc(10 * sizeof(int));
for (int i = 0; i < 10; ++i)
{
p[i] = i;//p[i]-->*(p+i)
}
free(p);
//基于C99语法的静态数组:处于栈内存当中,自动开辟回收,用于解决心脏起搏器问题!
//int * pC99 = (int []){ [4] = 10 };
//printf("%p \n", pc99);
printf("\n");
} int main03(void)
{
run();
printf("\n\n\n");//加速内存的回收动作!+防止Release模式!优化操作
run();
printf("\n\n\n"); system("pause");
} //05.指针变量可以指向任何内存地址:
// 无论是栈内存,堆内存,全局区,代码区
int main04(void)
{
int num = 30;
//int * pC99 = (int[30]) { 0 };
//pC99 = (int[10]) {0};//pC99是int*类型
//pc99 = 1;
int * pC99 = (int [30]) { [2] = 1, [4] = 10 };//静态数组
for (int i = 0; i < 30; ++i)
{
printf("%d \n", pC99[i]);
} system("pause");
} //06.区分静态分配和动态分配区别:
// int num=30;//静态分配:必须在编译时期,决定静态数组的元素个数
// int a[num];//栈上的静态分配-->可变长度的数组只有在GCC编译器当中实现,VC编译器当中不能进行实现
// 注:VC不支持位于栈内存的静态数组+GCC支持位于栈内存的静态数组!

程序片段(03):01.内存.c

内容概要:四大分配堆内存的函数

#include <stdio.h>
#include <stdlib.h> //01.内存四大分配函数:
// malloc<->calloc:
// malloc:内存不清零(参数:内存字节数)
// calloc:内存清零(参数1:数组元素个数+参数2:单个元素尺寸)
// realloc<->_recalloc:
// realloc:内存不清零(参数1:内存首地址,总内存字节数)
// 1.如果原始内存地址足够拓展,就在原始内存地址进行拓展
// 2.如果原始内存地址不够拓展,就在新地址内存进行拓展:
// 拷贝原始内存地址所对应的有效数据+回收原始内存地址数据
// 3.拓展之后的内存如果没有数据进行覆盖,就不回执行内存清零操作!
// _recalloc:内存清零(参数1:内存首地址+参数2:数组元素个数+参数3:单个元素尺寸)
// 1.如果原始内存地址足够拓展,就在原始内存地址进行拓展
// 2.如果原始内存地址不够拓展,就在新地址内存进行拓展
// 拷贝原始内存地址所对应的有效数据+回收原始内存地址数据
// 3.拓展之后的内存如果没有进行手动初始化,系统将会执行自动初始化操作!
int main01(void)
{
//int * p = (int *)malloc(100);//malloc不会初始化参数,参数是整体所占用的内存尺寸(字节数)!
int * p = calloc(25, sizeof(int));//calloc存在初始化参数,参数解释:第一个参数是元素个数,第二个参数是元素内存尺寸
printf("%p \n", p);
//for (int i = 0; i < 25; ++i)
//{
// p[i] = i;
//} system("pause");
} int main02(void)
{
int * p = malloc(10 * sizeof(int));//指针能够操作这片儿堆内存!
//int * p_p = malloc(100);
for (int i = 0; i < 10; ++i)
{
printf("%d \n", p[i] = i);
}
printf("p = %p \n", p); int * px = realloc(p, 200);//拓展内存,内存不清零
//返回值是内存首地址,说明拓展成功,后续地址拓展,拓展不成功,重新开辟内存
//原来的内存就被回收了
printf("px = %p \n", px);
for (int i = 0; i < 50; ++i)
{
px[i] = i;
printf("%d \n", px[i]);
}
//p[120387] = 10; system("pause");
} int main03(void)
{
int * p = calloc(25, sizeof(int));//会初始化为0,参数:数组元素个数+内存字节大小
//scanf("123");
printf("%p \n", p);
for (int i = 0; i < 25; ++i)
{
p[i] = i;
}
p = _recalloc(p , 50, sizeof(int));//内存清零操作
for (int i = 25; i < 50; ++i)
{
p[i] = i;
}
system("pause");
}

程序片段(04):main.c

内容概要:GccArray

#include <stdio.h>
#include <stdlib.h> //01.VC不支持栈内存动态数组,GCC支持栈内存动态数组!
int main()
{
int num=30;
int a[num];//栈上的动态分配
//int *pc99 = (int[30]){0}; //printf("Hello world!\n");
return 0;
}

20160211.CCPP体系详解(0021天)的更多相关文章

  1. 20160129.CCPP体系详解(0008天)

    程序片段(01):函数.c+call.c+测试.cpp 内容概要:函数 ///函数.c #include <stdio.h> #include <stdlib.h> //01. ...

  2. 20160226.CCPP体系详解(0036天)

    程序片段(01):01.多线程.c+02.多线程操作.c 内容概要:多线程 ///01.多线程.c #include <stdio.h> #include <stdlib.h> ...

  3. 20160208.CCPP体系详解(0018天)

    程序片段(01):main.c 内容概要:PointWithOutInit #include <stdio.h> #include <stdlib.h> //01.野指针详解: ...

  4. 20160206.CCPP体系详解(0016天)

    代码片段(01):.指针.c+02.间接赋值.c 内容概要:内存 ///01.指针 #include <stdio.h> #include <stdlib.h> //01.取地 ...

  5. 20160205.CCPP体系详解(0015天)

    程序片段(01):01.杨辉三角.c 内容概要:杨辉三角 #include <stdio.h> #include <stdlib.h> #define N 10 //01.杨辉 ...

  6. 20160204.CCPP体系详解(0014天)

    程序片段(01):define.h+data.h&data.c+control.h&control.c+view.h&view.c+AI.h&AI.c+main.c 内 ...

  7. 20160203.CCPP体系详解(0013天)

    程序片段(01):数组.c+02.数组初始化语法.c 内容概要:数组 ///01.数组.c #include <stdio.h> #include <stdlib.h> //0 ...

  8. 20160128.CCPP体系详解(0007天)

    以下内容有所摘取,进行了某些整理和补充 论浮点数的存储原理:float浮点数与double浮点数的二进制存储原理–>阶码 浮点数转二进制 1.整数int类型和浮点数float类型都是占用4个字节 ...

  9. 20160127.CCPP体系详解(0006天)

    程序片段(01):msg.c 内容概要:线程概念 #include <stdio.h> #include <stdlib.h> #include <Windows.h&g ...

随机推荐

  1. Java基础小记

    一.数据类型转换 1.引用数据类型 包装类型:Byte.Short.Long.Integer.Character.Float.Double.Boolean 2.基本类型与包装类转换 Java里有8种包 ...

  2. Myeclipse修改设置Default VM Arguments

    打开Windows-> Preferences 然后选择右侧菜单的Java->Installed JREs 点击右侧的jdk,然后点击"Edit"按钮 Default ...

  3. nginx 安装及简单配置(适用 小白)

    一.nginxNginx是一个异步框架的 Web服务器,也可以用作反向代理,负载平衡器 和 HTTP缓存,Nginx可以部署在网络上使用FastCGI脚本.SCGI处理程序.WSGI应用服务器或Phu ...

  4. 原生nodejs在线聊天系统

    前端自动化由来已久,最近为了编写自己的自动化工具,本人开始详细学习node,为了检验学习成果,决定编写一个类似于webqq的聊天系统.以下是该系统具有的模块. 登录模块(自动登录) 聊天模块(私聊,群 ...

  5. 浅谈轮播图(原生JavaScript实现)

    现在各种轮播图插件,玲琅满目,用起来也非常方便,通常只需要选择元素然后传入参数就可以了.但是,和授人以鱼不如授人以渔一样的道理,不管怎样最基本的轮播图原理还是应当掌握的.这样不仅有利于我们自己写出来满 ...

  6. 机器学习基石:07 The VC Dimension

    当N大于等于2,k大于等于3时, 易得:mH(N)被Nk-1给bound住. VC维:最小断点值-1/H能shatter的最大k值. 这里的k指的是存在k个输入能被H给shatter,不是任意k个输入 ...

  7. Git的安装和使用(托管至GitHub的方法)

    一.下载Git 1.下载 下载地址: https://git-scm.com/download/win 根据你的操作系统选择32位或者64位 2.安装过程一路next 3.检验安装是否成功 在桌面点击 ...

  8. Error:ivalue require as left operant of assignment

    Error:ivalue require as left operant of assignment 解答:该错误的意思是左操作数必须为左值,这个发生错误的原因在于赋值符号的左边不能是已确定的值,如: ...

  9. [Luogu 2062]分队问题

    Description 给定n个选手,将他们分成若干只队伍.其中第i个选手要求自己所属的队伍的人数大等于a[i]人. 在满足所有选手的要求的前提下,最大化队伍的总数. 注:每个选手属于且仅属于一支队伍 ...

  10. 【bzoj4011 hnoi2015】落忆枫音

    题目描述 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出这样一个问题. 「相信吧.不然我们是什么,一团肉吗?要不是有灵魂......我们也不可能再 ...