接口封装设计思想引导
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)指针也是一种变量,占有内存空间,用来保存内存地址
测试指针变量占有内存空间大小
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);
结论:指针的步长,根据所指内存空间类型来定。
//在函数调用哪个的时候实参的值机械的传给形参(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不行
