[day01]排序热身、数组做函数参数退化为指针、数据类型本质、变量本质、内存四区、铁律1
1.接口封装原型
第一套函数封装 |
#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); //客户端销毁环境 int cltSocket_destory(void *handle); #endif |
第二套函数封装 |
#ifndef _CLT_SOCKET2_H__ #define _CLT_SOCKET2_H__ //客户端初始化环境 int cltSocket_init2(void **handle); //5day //客户端发报文 int cltSocket_senddata2(void *handle, unsigned char *buf, int buflen); //客户端收报文 int cltSocket_resvdata2(void *handle , unsigned char **buf, int *buflen); //为什么这个地方换成了一个二级指针,而且又增加了一个接口 4day int cltSocket_resvdata_Free2(unsigned char *buf); //客户端销毁环境 //为什么这个地方又加了一个* 4day int cltSocket_destory2(void **handle); #endif //_CLT_SOCKET2_H__ |
2.选择排序回顾
#include <stdio.h> void selectSort(int *a, int num) { int i, j; int tmp; for (i=0; i<num; i++) { for (j=i+1; j<num; j++) { if (a[i] > a[j]) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } } } int main(void) { int a[6] = {2, 1, 3, 6, 5, 9}; int i; selectSort(a, 6); for (i=0; i<6; i++) { printf(" %d", a[i]); } return 0; } |
3.函数参数退化成指针
#include <stdio.h> //形参表出现int a[6]之类的,编译器并不会多分配内存,只会当作指针来处理 void printArray(int a[6]) { int i; int num1 = sizeof(a); int num2 = sizeof(*a); printf("printArray num1:%d num2:%d\n", num1, num2); for (i=0; i<6; i++) { printf(" %d", a[i]); } } int main(void) { int a[6] = {2, 1, 3, 6, 5, 9}; int num1 = sizeof(a); int num2 = sizeof(*a); printf("main num1:%d num2:%d\n", num1, num2); printArray(a); return 0; } |
4.数据类型本质
#include <stdio.h> int main(void) { int a[6] = {2, 1, 3, 6, 5, 9}; printf("a:%d &a:%d\n", a, &a); printf("a+1:%d &a+1:%d\n", a+1, &a+1); //a &a数据类型不一样,步长不一样 return 0; }
|
数据类型可以理解为创建变量的模具(模子),是 固定内存大小 的别名。 |
Void* 用于把一个不知道的数据类型传出来 |
5.变量的本质
(一段连续)内存空间的别名,变量是一个标号。
6.内存四区
内存四区模型 |
内存栈区也叫临时区。 |
全局区:相同的字符串只定义一份 |
#include <stdio.h> char* printStr1() { char *str1 = "abcd";/*在全局区分配内存都为abcd*/ return str1; } char* printStr2() { char *str1 = "abcd";/*在全局区分配内存都为abcd*/ return str1; } char* printStr3() { char str[20]; strcpy(str, "abcd"); return str; /*这里将在栈上分配的内存返回,这是初学者经常犯的错误。*/ } int main(void) { printf("%x, %x\n", printStr1(), printStr2()); printf("%s\n", printStr3()); return 0; }
|
指针变量和它所指向的内存空间变量是两个不同的概念 |
7.堆栈生长方向
栈生长方向向下,也就是栈开口方向实际上向下。 |
堆生长方向向上。 |
测试代码 #include <stdio.h> #include <stdlib.h> // declare malloc int main() { int *a1 = NULL; int *b1 = NULL; a1 = (int *)malloc(100); b1 = (int *)malloc(100); printf("%x, %x\n", &a1, &b1); // 28ff1c, 28ff18 big->small printf("%x, %x\n", a1, b1); // 4f0ff0, 4f1060 small->big return 0; } |
heap、stack生长方向和内存存放方向是两个不同概念 /*buf几地址最大?*/ { char buf[3]; buf[0] buf[1] buf[2] } /*buf[2]地址最大*/ |
8.铁律1-指针的数据类型到底是什么
指针的数据类型是指它所指向的内存空间的数据类型,指针的数据类型具有依附特性。 |
结论:指针的步长,根据所指内存空间类型来定。 |
9.有关字面量的理解
{ //10字面量 放在不能取地址,没有放在堆栈、全局区,可以按照放在代码区之类的区域内理解 int *a = &10; } |
10.指针赋值字符串注意
给没有动态分配内存的字符指针赋值 |
#include <stdio.h> #include <stdlib.h> int main(void) { char *p = NULL; p = "a"; // 注意这里"a"存放在常量区,不要误以为p没有分配内存不能存 // 其实并不是p去存a,而是p去存常量区的"a"的地址 printf("p:%d\n", p); printf("string a:%d\n", "a"); system("pause"); return 0; } |