C++封装随笔

1接口的封装和设计思想入门

接口的封装和设计思想入门

第一套api函数

#ifndef _CLT_SOCKET_H__

#define _CLT_SOCKET_H__

 

//客户端初始化环境

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

 

//客户端发报文

int cltSocket_senddata(void *handle, unsigned char *buf, int buflen);

 

//客户端收报文

int cltSocket_resvdata(void *hanle , unsigned char *buf, int *buflen);

 

 

//4 客户端销毁环境

int cltSocket_destory(void *handle);

 

#endif

 

第二套api函数

 

//第二套api函数

#ifndef _CLT_SOCKET_H__

#define _CLT_SOCKET_H__

 

//客户端初始化环境

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

 

//客户端发报文

int cltSocket_senddata2(void *handle, unsigned char *buf, int buflen);

 

//客户端收报文

int cltSocket_resvdata2(void *hanle , unsigned char **buf, int *buflen);

//为什么这个地方换成了一个二级指针,而且又增加了一个接口 4day

int cltSocket_resvdata_Free2(unsigned char *buf);

 

//4 客户端销毁环境

//为什么这个地方又加了一个* 4day

int cltSocket_destory2(void **handle);

 

#endif

我们找到了一套标准,我们可以高效的学习,更重要的是,我们能务实的,集中话题学习这套api函数

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

 

 

3学习标准热身

排序

选择法排序思想总结

 

核心排序代码

printfArray3(a);

 

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

{

for (j=i+1;j<10; j++)

{

if (a[i] < a[j])

{

tmp = a[i];

a[i] = a[j];

a[j] = tmp;

}

}

}

 

printf("\n?¨°?¨®:");

 

结论

//1数组做函数参数,会退化为指针

//2在形参里面出现的char buf[30] int a[10] c/c++编译器会把它当做指针,也不会主动的多分配内存,cc++编译器会自动优化

// int i = 0;

int num1 = sizeof(a);

int num2 = sizeof(*a);

int num = sizeof(a)/sizeof(*a); 

int num1 = sizeof(a); //数据类型不一样

//3 sizeof(a)大小不一样的实质是a的数据类型不一样

 

 

4数据类型本质剖析

数据类型问题抛出

压死初学者的三座大山

1、数组类型

2、数组指针

3数组类型和数组指针的关系

void main()

{

int a[10] = {1, 3, 44, 2, 3, 44, 5, 5,6, 67};

printf(“a:%d &a:%d \n”, a, &a); //a &a大小一样

printf(“a+1:%d &a+1:%d \n”, a+1, &a +1 ); //+1 大小不一样

//a &a数据类型不一样 步长不一样

//压死出血

system(“pause”);

}

数据类型分为两种,简单、一个复杂,思考复杂数据类型的时候,不能用简单数据类型思考之。。。。。抛砖

//写一个函数 把内存地址给传出被调用函数,方法有2

 

结论:

数据类型本质:固定大小内存的别名

数据类型取别名 typdedef 抛出问题:

如何表达:int array[10]   int add(int a, int d);//15

 

 

5变量的本质

修改变量的方法

两种+引用

变量的本质:连续内存块的别名,变量是一个标号。再抛砖

程序的内存四区图,画变量示意图时,主要把变量放在外面,内存空间留出来

内存空间可以再取给别名吗?

 

 

6内存四区概念

基本概念

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

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

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

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

char * getstring3()

{

char buf[30];

strcpy(buf, "abcde");

return buf;

}

 

 

 

 

 

 

 

 

铁律1

铁律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);

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

 

 

 

 

 

 

 

 

不断地修改指针变量的值含义场景建立

//不断地修改指针变量的值含义

//需要建立场景,解决指针乱指问题

void main()

{

int i = 10;

char buf[20];

char *p = NULL;

 

strcpy(buf, "a234567899987654");

 

p = &buf[0];

p = &buf[1];

p = &buf[2];

p = &buf[3];

p = &buf[4];

 

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

{

p = &buf[i];

}

}

 

 

2经验话语

#ifndef _CLT_SOCKET2_H__

#define _CLT_SOCKET2_H__

#endif 

 

// 避免在.c里面 重复包含多次头文件

#include "cltsocket.h"

#include "cltsocket.h"

#include "cltsocket.h"

 

Shift+del建组合删除一行

Ctlr+u 让单词从小写变大写

Shift+ctrl+u 从大小变小写

 

//避免多次重复包含 整个思路分析

C语言中的灰色地带这种问题,往后放

 

 

有关字面量

有关字面量的理解

{

//10 字面量  放在不能取地址 没有放在堆栈、全局区,可以按照放在代码区之类的区域内理解它。

int *a = &10;

}

 

怎么样理解(多级)指针做函数参数,

//对参数的指针类型应该怎么理解

//理解角度需要从两个角度出发

//第一个角度:站在c/c++编译器的角度 对形参,如果是指针类型,c编译器只会把它当作一个指针变量来看。(配四个自己的内存)。

////char *p7 形参 是变量

//第二个角度:我们只有在使用指针所指向的内存空间的时候,我们才去关心内存是一维的,还是二维的。

/*

void senddata01(char    *p1); void senddata01(char*            p1);

void senddata02(char **    p1); void senddata02(char *     *p1);  void senddata02(char         **p1);

void senddata03(char ***p1);

void senddata04(char *p[]); void senddata04(char *     p[]);  void senddata04(char *p    []);

void senddata05(char (*p)[10]); void senddata05(char (*p)             [10]);

void senddata05(char *****p4);

*/

 

 

 

内存块数据打包

//(unsigned char *buf +len)内存块的数据打包

有关[] *

//buf[i]-->buf[0+i];--->*(p+i)  ---> p[i]

//站在c++编译器的角度, *p 相当于我们程序员手工(显示)利用间接赋值,去操作内存

//[]怎么理解,只不过是c++编译器帮我们程序员做了一个*p的操作

 

 

char buf[100] = "abcdefg";

char *p = NULL;

 

 

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

{

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

}

 

 

printf("\n");

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

{

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

}

 


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

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

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

条件1:定义了一个变量(实参)定义了一个变量(形参)

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

条件3//*p形参,去间接的修改实参的值

main --->func

*/

//间接赋值成立的三个条件,应用起来。。。。

//123 写在一个函数里面,那么成了第一个应用场景

//12    3 //间接赋值是指针存在的最大意义

//1      23  //抛砖,,,,到时候,要认识啊。

//间接赋值的应用场景有2

//场景1:在函数指针  *p1++ = *p2++

//场景2:指针做函数参数,通过*p形参求间接的修改实参的值,这才是指针存在的最大意义、。

//这才是C语言特有的现象,才是指针的精华

//*p间接赋值是指针存在的最大意义(现实意义)

接口的封装和设计

//函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p

//来改变实参,把运算结果传出来。

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

推论

//指针做函数参数

//函数调用过程中,

//1级指针(通常是形参,)去修改0级指针(通常是实参)的值

//2级指针(通常是形参,)去修改1级指针(通常是实参)的值

//3级指针(通常是形参,)去修改2级指针(通常是实参)的值

//8级指针(通常是形参,)去修改7级指针(通常是实参)的值

//n级指针(通常是形参,)去修改n-1级指针(通常是实参)的值

/*

整个C/C++领域值得我们做技术推演的领域

0--1

1->2 2->3

 

c++多态(函数指针做函数参数)

 

Aop切面编程(2-3

*/

03字符串专题讲座

内存模型

//1c中没有字符串这种类型,是通过字符串数组(char buf[100])去模拟

//2 字符串和字符串数组的区别 是不是 带有\0

//print函数是c库函数,它就是按照C风格字符串进行输出数据

 

//通过字符串常量初始化字符串数组

//通过这种方法它会自动给你\0

char buf4[] = "abcdefg";

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

 

//

//strlen() 是一个函数 求字符串的长度(不是求字符数组的长度),它的长度不包括\0

//sizeof() 是一个操作符,求数据类型(实体)的大小

int main13()

{

char buf[20]="aaaa";

int a = 10; //字面量

 

char buf2[] = "bbbb";

//char ***********************************************p1 = "111111";

char *p1 = "111111";

 

char *p2 = malloc(100);

strcpy(p2, "3333");

//&a; //&a表达式 表达式的运算结果放在寄存器里

}

 

//buf[i]-->buf[0+i];--->*(p+i)  ---> p[i]

//站在c++编译器的角度, *p 相当于我们程序员手工(显示)利用间接赋值,去操作内存

//[]怎么理解,只不过是c++编译器帮我们程序员做了一个*p的操作

 

//因为后缀++的优先级,高于,*p;

void copy_str4(char *from , char *to)

{

while((*to ++ = *from++) != '\0')

{

;

}

}

 

 

重要概念概念

C语言中使用字符数组来模拟字符串

C语言中的字符串是以’\0’结束的字符数组

C语言中的字符串可以分配于栈空间,堆空间或者只读存储区

03 字符串操作

数组法,下标法

字符数组名,是个指针,是个常量指针;

字符数组名,代表字符数组首元素的地址,不代表整个数组的。

如果代表这个数组,那需要数组数据类型的知识!

 

字符串做函数参数

void copy_str01(char *from, char *to)

{

for (; *from!='\0'; from++, to++)

{

*to = *from;

}

*to = '\0';

}

 

void copy_str02(char *from, char *to)

{

while(*from!='\0')

{

*to++ = *from++;

}

*to = '\0';

}

 

void copy_str03(char *from, char *to)

{

while( (*to=*from) !='\0')

{

to++;

from++;

}

}

 

void copy_str04(char *from, char *to)

{

while( (*to++=*from++) !='\0')

{

;

}

}

 

int copy_str05_good(const char *from, char *to)

{

if (from==NULL || to==NULL)

{

printf("func copy_str05_good() err. (from==NULL || to==NULL)\n");

return -1;

}

 

while( (*to++=*from++) !='\0')

{

;

}

return 0;

}

 

字符串操作典型错误

建立一个思想:是主调函数分配内存,还是被调用函数分配内存;

越界 语法级别的越界

char buf[3] = "abc";

 

 

 

越界

越界 语法级别的越界

char buf[3] = "abc";

 

 

不断修改内存指针变量

越界

 

void copy_str_err(char *from, char *to)

{

char *fromtmp = from;

for (; *from!='\0'; from++, to++)

{

*to = *from;

}

*to = '\0';

printf("to:%s", to);

printf("from:%s", from);

}

 

 

 

4、你向外面传递什么

1、临时str3内存空间

// char *str_cnct(x,y)     /*简化算法*/

// char *x,*y;

char *str_cnct(char *x, char* y)     /*简化算法*/

{

char str3[80];

char *z=str3; /*指针z指向数组str3*/

while(*z++=*x++);

z--;                /*去掉串尾结束标志*/

while(*z++=*y++);

z=str3;  /*str3地址赋给指针变量z*/

return(z);

}

2、经验要学习

while(*z++=*x++);

z--;                /*去掉串尾结束标志*/

 

char *str_cnct(char *x, char* y)     /*简化算法*/

{

char * str3= (char *)malloc(80)

char *z=str3; /*指针z指向数组str3*/

while(*z++=*x++);

z--;                /*去掉串尾结束标志*/

while(*z++=*y++);

z=str3;  /*str3地址赋给指针变量z*/

return(z);

}

 

char *str_cnct(char *x, char* y)     /*简化算法*/

{

If (x == NULL)

{

Return NULL;

}

char * str3= (char *)malloc(80)

char *z=str3; /*指针z指向数组str3*/

while(*z++=*x++);

z--;                /*去掉串尾结束标志*/

while(*z++=*y++);

z=str3;  /*str3地址赋给指针变量z*/ note:

return(z);

 

}

Main ()

{

Char *p = str_cnct(“abcd”, “ddeee”);

If (p != NULL) {Free(p) ;p = NULL}//yezhizhen

}

int getKeyByValude(char *keyvaluebuf,  char *keybuf,  char *valuebuf, int * valuebuflen)

{

int result = 0;

char *getbuf = new char[100];

memset(getbuf, 0, sizeof(getbuf));

 

char *trimbuf = new char[100];

memset(trimbuf, 0, sizeof(trimbuf));

 

int destlen = strlen(keyvaluebuf);

 

if (keybuf == NULL || keyvaluebuf == NULL || valuebuf == NULL/* || valuebuflen == NULL*/)

{

result = -1;

return  result;

}

 

if (strstr(keyvaluebuf, keybuf) == NULL)

{

result = -1;

return result;

}

else

{

for (int i = 0; i < destlen; i++)

{

if (*keyvaluebuf == '=')

{

*keyvaluebuf++;

break;

}

keyvaluebuf++;

}

while(*keyvaluebuf != '\0')

{

*valuebuf = *keyvaluebuf;

valuebuf++;

keyvaluebuf++;

}

*valuebuf = '\0';

}

 

int len = strlen(valuebuf);

return result;

}

 

字符串项目开发模型

strstr+while语句进行符合条件字符串查找

 

demo04_两头堵

demo05_字符串反转

const专题讲座

1、 const基础知识(用法、含义、好处、扩展)

 

int main()

{

const int a;  //

int const b; 

 

const int *c;

int * const d;

const int const *e ;

 

return 0;

}

 

Int func1(const )

初级理解:const是定义常量==const意味着只读

含义:

//第一个第二个意思一样 代表一个常整形数

//第三个 c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改)

//第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)

//第五个 e一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)

Const好处

//合理的利用const

//1指针做函数参数,可以有效的提高代码可读性,减少bug

//2清楚的分清参数的输入和输出特性

结论:

//指针变量和它所指向的内存空间变量,是两个不同的概念。。。。。。

//const 是放在*的左边还是右边 看const是修饰指针变量,还是修饰所指向的内存空变量

 

04二级指针输入模型

 

二级指针内存模型图

 

 

 

 

数组名

1数组名

//二维数组也是线性排列的

void printArray(int *a, int size)

{

int i = 0;

 

printf("printArray: %d\n", sizeof(a));

 

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

{

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

}

}

 

int main()

{

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

char cc[10][30];

 

 

int* p = &a[0][0];

 

printf("sizeof(&a):%d \n", sizeof(&a));

printf("sizeof(a):%d \n", sizeof(a));

printf("sizeof(*a):%d \n", sizeof(*a));

 

printf("sizeof(&cc):%d \n", sizeof(&cc));

printf("sizeof(cc):%d \n", sizeof(cc));

printf("sizeof(*cc):%d \n", sizeof(*cc));

 

//printArray(p, 6);

 

getchar();

 

return 0;

}

2、本质分析

//int a[5] 一维数组名代表数组首元素的地址

//int a[5] ===> a的类型为int*

 

//二维数组名同样代表数组首元素的地址

//int b[2][5]===>b的类型为int(*)[5]

 

//测试如何测试:指针也是一种数据类型,它的数据类型是指它所执行的内存空间的数据类型

//如何测试b的步长?

//推导。。。。。。。

 

//结论:二维数组名 char cc[10][30] 是一个数组指针,char (*)[30]

 

2多维数组做函数参数退化

1、 C语言中只会以机械式的值拷贝的方式传递参数(实参把值传给形参)

int fun(char a[20], size_t b)
{
   printf("%d\t%d",b,sizeof(a));
}

原因1:高效

原因2
C语言处理a[n]的时候,它没有办法知道n是几,它只知道&n[0]是多少,它的值作为参数传递进去了
虽然c语言可以做到直接int fun(char a[20]),然后函数能得到20这个数字,但是,C没有这么做

 

2、二维数组参数同样存在退化的问题

二维数组可以看做是一维数组

二维数组中的每个元素是一维数组

二维数组参数中第一维的参数可以省略

void f(int a[5]) ====void f(int a[]); === void f(int* a);

void g(int a[3][3])==== void g(int a[][3]); ==== void g(int (*a)[3]);

3、等价关系

 

数组参数 等效的指针参数

 

一维数组 char a[30] 指针 char*

指针数组 char *a[30] 指针的指针 char **a

二维数组 char a[10][30] 数组的指针 char(*a)[30]

char * a[30]  char(*a)[30]  char(*a)(30)

怎么区分:指针数组、数组指针

 

 

3数组指

posted @ 2017-11-07 22:05  physique  阅读(1160)  评论(0编辑  收藏  举报