接口封裝設計思想引導
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
{
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:當我們程序員要使用指針所指向的內存空間的時候,我們關心,這個內存塊是一維的,還是二維的。
//一般情況:1級指針代表1維,二級指針代表二維。。。
//如果有超過char ***級及3級以上的指針,則不代表幾維的內存。。。
//多維數組做函數參數,一般情況下,只能表達到二維,
//如果是三維內存(我們程序員起的名字),已經沒有意義。
//證明一下多維數組的線性存儲
//線性打印