”内存四区,一级指针,字符串” 学习笔记

01内存四区专题讲座

接口封装和设计思想引导

接口封装设计思想引导

Sckclient客户端api模型设计

第一套api函数

#ifndef _SCK_CLINT_H_

#define _SCK_CLINT_H_

 

//函数声明

// 1、客户端环境初始化

int sckClient_init(void **handle); //5 day

//

// 2、客户端发送报文

int sckClient_send(void *handle, unsigned char *data, int datalen);

// 3、客户端端接受报文

int sckClient_rev(void *handle, unsigned char *out, int *outlen); //1

// 4、客户端环境释放

int sckClient_destroy(void *handle);

 

#endif

 

 

、、

 

//条件编译 避免头文件多次包含

 

#ifndef _SCK_CLINT02_H_

#define _SCK_CLINT02_H_

 

#ifdef  __cplusplus

extern "C" {

#endif

 

//函数声明

// 1、客户端环境初始化

int sckClient_init2(void **handle); //5 day

//

// 2、客户端发送报文

int sckClient_send2(void *handle, unsigned char *data, int datalen);

// 3、客户端端接受报文

int sckClient_rev2(void *handle, unsigned char **out, int *outlen); //1

int sckClient_rev2_Free(void **p); //1

// 4、客户端环境释放

int sckClient_destroy2(void **handle);

 

#ifdef  __cplusplus

}

#endif

 

 

#endif

我们找到了一套标准,我们可以高效、有目的的学习。

Socket动态库业务模型思路分析

 

经验话语

Shift+del 删除一行 ctrl+shift+u大小 ctrl +u 小写

Alt+F9

F5在多个断点间切换

 

 

 

排序热身及数组做函数参数

 

//当数组当做函数参数的话的时候会退化为指针

int printfArray(int a[])

{

         int i = 0;

         printf("排序之前\n ");

         for (i=0; i<10; i++)

         {

                   printf("%d ", a[i]);

         }

         return 0;

}

 

//int a[10]  -=-->int a[] ---->int *a

//数组做函数形参的时候,如果在形参中定义int a[10]语句,

//c/c++编译器 会做优化,技术推演如下

//int a[10]  -=-->int a[] ---->int *a

//总结:函数调用的时候,把数组首地址和有效数据长度传给被调用函数才是最正确的做法

 

int printfArray04(int *a, int num)

{

 

         int i = 0;

         printf("排序之前\n ");

         for (i=0; i<num; i++)

         {

                   printf("%d ", a[i]);

         }

         return 0;

 

}

 

数据类型本质

数据类型可理解为创建变量的模具(模子);是固定大小内存的别名。

sizeof是操作符,不是函数;sizeof测量的实体大小为编译期间就已确定

数据类型可以取别名、测量大小

数据类型的封装

Void数据类型的封装

数据类型的引申

C一维数组、二维数组有数据类型吗 3

C语言中,函数是可以看做一种数据类型吗?15

 

数组类型三大技术难点,压死初学者的三座大山

 

 

 

变量本质

变量本质:(一段连续)内存空间的别名、内存空间的标号

修改变量的3种方法

1、直接

2、间接。内存有地址编号,拿到地址编号也可以修改内存;于是。。。横空出世了!

3、c++ 引用

总结:1对内存 可读可写; 2通过变量往内存读写数据,3不是向变量读写数据。4向变量代表的数据空间读写数据。变量跑到什么地方去了?

 

 

内存四区

1、  内存四区模型和函数调用模型

 

基本概念

函数1调用函数2,函数1称为主调函数 函数2称为被调用函数

规则1:Main(主调函数)分配的内存(在堆区,栈区、全局区)都可以在被调用函数里使用吧。

规则2:在被调用函数里面分配的内存

 

1、如果在被调用函数里面的临时区(栈)分配内存,主调用函数是不能使用的。

全局区://c++编译器优化

char *getStr1()

{

         char *p = "abcd1";

         return p;

}

 

char *getStr2()

{

         char *p = "abcd1";

         return p;

}

//

临时区stack

char * getStr3()

{

         char buf[100];

         memset(buf, 0, sizeof(buf));

         strcpy(buf, "abcd1");

         return buf;

}

//栈属性

//栈向下生长的,

//栈的生长方向和内存空间buf存放方向是两个不同的概念

//堆向上生长的,

//演示:stack生长方向

int main31()

{

         float *p1 = NULL;

         int *p2 = NULL;

         int a = 0;

         int b= 0;

         char buf[16];

         printf("&p1:%x, &p2:%x, &a:%x, &b:%x \n", &p1, &p2, &a, &b);

         printf("&buf[0]:%x, &buf[1]:%x", &buf[0], &buf[1]);

 

         getchar();

}

 

//软件开发中 注意野指针

//仔细观察malloc内存地址大小

//演示heap生长方向

int main32()

{

         int a = 0;

         int b = 0;

         char *p1 = NULL;

         char *p2= NULL;

         p1 = (char *)malloc(16);

         p2 = (char *)malloc(16);

 

         printf("\n p1:%x, p2:%x", p1, p2);

         printf("\n &p1:%x, &p2:%x", &p1, &p2);

 

         //通过内存地址间接赋值

         *((char *)0x394da0) = 'a';

         *((char *)0x394da1) = 'b';

 

         //通过内存地址间接修改内存空间的值

         //通过变量名访问内存空间

         //通过内存地址间接访问内存空间 这就是C语言的灵活性,也是c语言的精华

         printf("\np2[0]:%c", p2[0]);

         printf("\np2[1]:%c", p2[1]);

 

         if (p1 != NULL)

         {

                   free(p1);

         }

         if (p2 != NULL)

         {

                   free(p2);

         }

         getchar();

         return 0;

}

 

 

 

铁律1:指针是一种数据类型   

1)指针也是一种变量,占有内存空间,用来保存内存地址

测试指针变量占有内存空间大小

2)*p操作内存

在指针声明时,*号表示所声明的变量为指针

在指针使用时,*号表示 操作 指针所指向的内存空间中的值

         *p相当于通过地址(p变量的值)找到一块内存;然后操作内存

         *p放在等号的左边赋值(给内存赋值)

         *p放在等号的右边取值(从内存获取值)

3)指针变量和它指向的内存块是两个不同的概念

//含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++

//含义2 给*p赋值*p='a'; 不会改变指针变量的值,只会改变所指的内存块的值 

//含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!

//含义4 =左边char *p

//含义5 保证所指的内存块能修改

4)指针是一种数据类型,是指它指向的内存空间的数据类型

含义1:指针步长(p++),根据所致内存空间的数据类型来确定

p++=è(unsigned char )p+sizeof(a);

结论:指针的步长,根据所指内存空间类型来定。

 

02经验话语

 

//在函数调用哪个的时候 实参的值机械的传给形参(c int数组场景)

//关于形参:

         写在函数上形参变量,还是写在函数里面的变量,

                   从CC++编译的角度来讲,是没有任何区别的(分配4字节内存);

                   只不过是 写在函数上形参变量 ,具有对外的属性而已

//数据类型分为两种,一个是简单的数据类型,一个是复杂的数据类型。碰见复杂的数据类型不能用简单的数据类型的思维去思考它。抛砖

 

/*

int getbuf01(char   *p); int getbuf01(char*     p);

int getbuf02(char **p); int getbuf02(char *   *p); getbuf02(char **        p);

int getbuf03(char (*p)[]); int getbuf03(char (*p)      []);  int getbuf03(char (     *p)[     ]);

int getbuf03(char p[10][30]);

int getbuf04(char *****p);

*/

 

//角度1站在c++编译器的角度 指针就是一个变量,除此之外啥也不是!

//不管是1个* 还是8个*对c++编译器来讲,只会分配4个字节内存

//角度2:当我们程序员要使用指针所指向的内存空间的时候,我们关心,这个内存块是一维的,还是二维的。

 

C和java的区别

C可以在临时区分配内存块。。。。。。。java不行

 

 

         {

                   char *p1 = 0; //

                   strcpy(p1, "abcdefg");

                   strcpy(0, "abcdefg"); //抛砖:在两个函数里面就不一定能明白

 

         }

        



【】*的本质

         //[] *的本质到底是什么?

         //*p 是我们程序员手工的(显示)去利用间接赋值

         //【】 只不过是,c/c++ 编译器帮我们做了一个*p的操作。。。。。。

         // buf4[i]======> buf4[0+i] ====>  *(buf4+i)

         //===*(buf4+i)   --> bu4[i];

//操作数组的方法

//下标法和指针法

void main()

{

         int i = 0;

         char *p = NULL;

         //通过字符串初始化字符数组 并且追加\0

         char buf4[] = "abcd";

        

         for (i=0; i<strlen(buf4); i++)

         {

                   printf("%c", buf4[i]); //p[]

         }

        

         //[] *的本质到底是什么?

         //*p 是我们程序员手工的(显示)去利用间接赋值

         //【】 只不过是,c/c++ 编译器帮我们做了一个*p的操作。。。。。。

         // buf4[i]======> buf4[0+i] ====>  *(buf4+i)

         //===*(buf4+i)   --> bu4[i];

 

         printf("\n");

 

         p = buf4;

         for (i=0; i<strlen(buf4); i++)

         {

                   printf("%c", *(p+i)); //*p

         }

 

         system("pause");

}

        

 

 

 

02铁律2*p是指针存在的最大意义

 

间接赋值成立的是3个条件

 

/* 间接赋值成立的三个条件

条件1  //定义1个变量(实参) //定义1个变量(形参)

条件2//建立关联:把实参取地址传给形参

条件3://*形参去间接地的修改了实参的值。

*/

Int iNum = 0; //实参

int *p = NULL;

p = &iNum;

iNum = 1;

*p =2 ; //通过*形参 == 间接地改变实参的值

*p成立的三个条件:

间接赋值成立三个条件的几种组合

123在一个函数里面

12    3 两个函数

1              23两个函数

 

//间接赋值条件应用深入分析 三个条件的组合,分别产生三种很重要的语法现象

//123都写在一个函数里面

//12写在一个函数里面  3 写在另外一个函数里面

//1 写在一个函数里面  23 写在另外一个函数里面 抛砖。。。到时候别不认识啊。。。。。

间接赋值应用场景12

场景1:一个函数之内  *p1++ = *p2++

场景2:int getFileLen(int *a )

间接赋值的推论

 

//在函数调用的时候

/*

用1级指针形参,去间接修改了0级指针(实参)的值。。

用2级指针形参,去间接修改了1级指针(实参)的值。。

用3级指针形参,去间接修改了2级指针(实参)的值。。

用n级指针形参,去间接修改了n-1级指针(实参)的值。。

*/

 

间接赋值的工程意义

 

//函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p,来改变实参,把运算结果传出来。

//指针作为函数参数的精髓。

//C语言特有的想象,是C语言的精华。。。

 

寻路

指针做函数参数是我们的研究重点。。。。。

指针是子弹、函数像枪管,,子弹枪管才能发挥它的威力。。。。。。。

 

下一步你的方向

1、  指针学完了。。。。。你只是c语言的半壁江山。。。。。

2、  函数指针。。。。

 

 

 

 

字符串专题讲座

字符串操作基础

//c语言里面没有字符串这种类型。。。。。

//通过字符数组来模拟字符串

//C风格字符串是以零结尾的字符串

void main11()

{

         //字符数组初始化

         //指定长度 如果定义的长度剩余部分补充0

         char buf1[100] = {'a', 'b', 'c'};

         //不指定长度

         char buf2[] = {'a', 'b', 'c'};

         char buf3[] = {'a', 'b', 'c','\0'};

 

         //通过字符串初始化字符数组 并且追加\0

         char buf4[] = "abcdefg";

 

         printf("%s\n", buf4 );

 

         system("pause");

}

printf("%s\n", buf4 );

         printf("sizeof(buf4): %d\n ", sizeof(buf4)); //注意sizeof是对数组类型进行大小测量 包括了\0

         printf("strlen(buf4): %d \n", strlen(buf4));//strlen是求字符串的长度不包括\0

 

 

 

字符串内存模型

一级指针内存模型图

 

字符串做函数参数

 

C库字符串API函数调用经验谈

字符串copy函数技术推演

//C字符串函数调用方法经验谈

//站在内存四区模型和函数调用模型去思考函数。。。。。api接口

/*

1)  主调函数 被调函数

         a)      主调函数可把堆区、栈区、全局数据内存地址传给被调用函数

         b)      被调用函数只能返回堆区、全局数据

         2)  内存分配方式

         a)      指针做函数参数,是有输入和输出特性的。

         */

 

 

铁律3 深入理解指针必须和内存四区概念相结合,注意指针的输入输出特性

 

//C字符串函数调用方法经验谈

//站在内存四区模型和函数调用模型去思考函数。。。。。api接口

/*

1)  主调函数 被调函数

         a)      主调函数可把堆区、栈区、全局数据内存地址传给被调用函数

         b)      被调用函数只能返回堆区、全局数据

         2)  内存分配方式

         a)      指针做函数参数,是有输入和输出特性的。

         */

字符串操作常见工程开发模型

         业务模型&业务测试模型分离===》接口封装和设计第一步

 

被调用函数分配内存如何传出两种方法

 

//被调用函数分配内存吧结果甩出来有两种方法

//return

//指针做函数参数

char * getBuffer()

{

         char buf[109];

         char *p = (char *)malloc(199);

         //char *p2= (char *)malloc(199);

         return p;

}

 

项目开发中字符串模型建立

         strstr的whiledowhile模型

         两头堵模型(两种写法)

                   项目经验:in内存块,一般不要做修改,const出现的原因

         字符串反转模型

         两个辅助指针变量挖字符串

 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值