基本数据类型
-
数值类型
整型:int short long longlong 字节数:4 2 4 8 浮点型:float double 字节数: 4 8
int 和 long int的区别?
二者的区别主要体现在不同的编译方式上,在不同的操作系统中表现出的位数不同,在早期的16位的系统上,int是2字节,long是4字节;后来发展到32位的系统,int和long相同,都是4字节;随着系统的发展现在到了64位的操作系统,int是4字节,long是八字节
关于longlong
关于long long (1)long long在win32中是确实存在,长度为8个字节;定义为LONG64。 为什么会出现long int呢,在win32现在系统中,长度为4;在历史上,或者其他某些系统中,int长度为2,是short int。 即便是long long,在TI的有款平台中,长度为5 也就是说,每种类型长度,需要sizeof才知道,如果可能,最好用union看看里面的数据,可以消除一些类型的假象长度。 (2)visual c++ 6.0中不支持,long long int,是在vc99中添加此功能的,所以我们在vc6.0中编译有long long 的数据时,会出错,但是在VS更高的版本中,是能通过的
-
字符类型
char 大小为1字节
-
指针类型:不管什么指针,大小都是4字节
-
空类型:声明函数无返回值或者没有参数。声明空类型指针
-
自定义类型
-
结构体
结构体对齐方式:
- 结构体第一个成员必须放到0偏移处
- 结构体成员的偏移量为自身的整数倍
- 结构体的大小只能是自身最大成员变量大小的整数倍
空结构体的大小为1
柔性数组
-
共用体
所有成员公用一块内存,共用体所占内存的长度时最长成员的字节长度,有效提高了内存的利用效率。
union 共用体名 { 成员列表; }
-
枚举
【1】. 枚举类型如果没有初始化,默认第一个成员从0开始
【2】.枚举与宏的区别:
- 宏是在与编译阶段进行的文本替换,而枚举是在编译阶段进行的处理,宏不能调试,枚举可以进行调试。
- 宏定义需要一条一条的进行定义,而枚举只需要定义一次就可以了。
- 宏作为指令存储在代码段;枚举作为常量存储在数据段;
- 枚举是将一类型的信息集合在一起,而宏相对比较分散一点
- 枚举中的每一项元素都是常量,是不可以赋值和更改的,但是我们可以在声明这个枚举的时候给个初始值。
-
main函数的参数
- 第一个参数是int argc,代表包含文件名在内的命令行参数的个数;
- 第二个参数char *argv[],是一个指针数组,里面包含文件名在内的命令行参数的首地址,数组的最后以NULL结尾。
- 第三个参数char * envp[],表示环境变量。
指针
二级指针
- 二级指针存放的是一级指针的地址
- 对二级指针进行一次“*”引用。就可以访问一级指针,对其进行“**”引用就可以访问一级指针所指向的空间。
函数指针
- 定义:函数指针还是一个指针,只不过是指向一个函数的指针,在使用之前必须进行初始化,使他指向某个函数。
char* (*p)(char*);//p是一个函数指针,所指向的函数类型是返回值为char* ,有一个char*型参数的函数
-
函数指针数组:是一个存放函数指针的数组。
int (*(*p)[3])(int);//p是一个具有三个元素的函数指针数组,p里面存放的函数指针所指向的函数类型是返回值为int参数为空的函数
-
函数指针最常见的两个用途:转换表和回调函数。回调函数是将函数指针作为参数传递给另一个函数。
指针数组与数组指针
指针数组
指针数组是一个数组,只不过数组里面存放的都是指针
int *p[];//因为[]比*优先级高,所以指针数组一定是不加()的,让变量名先与[]结合
数组指针
数组指针是一个指针,只不过它指向的的是一个数组,所以当指针加一是,他跳过的是整个数组。
int(*P)[3];//[]比*的优先级要高,所以要先加()让*与变量名先进行结合
指针和数组之间的恩怨
- 下标与*访问方式:数组有两种访问方式,一种是下标访问,一种是*访问,下标访问最终还是先被转化成 *访问的形式再进行访问的。
- 数组参数和指针参数:当一位数组或者一级指针作为实参时,形参可以声明为数组形式,也可以声明成指针形式。这是因为一维数组做事餐时传递过去的是首元素地址,所以才可以用指针的形式接受,但一定要明白数组和指针之间是没有关系的,完全是两个概念。
- 二维数组参数和二级指针参数:二维数组参数与数组指针参数是等效的;二级指针参数与指针数组参数是等效的。
内存管理
内存分配函数
-
malloc和calloc
void* malloc(要开辟的字节数); void* calloc(元素个数,每个元素的字节数); /* 这两个函数如果开辟失败会返回一个空指针,所以要对他们的返回值进行判空操作;他们返回的是空类型,所以要强制类型转换之后才能使用。calloc会将开辟空间默认初始化为0. */
-
realloc
void realloc(原先已经分配的地址,重新要分配的字节数); /* realloc用来修改原先已经分配大小的内存块。注意:realloc失败后也会返回空,所以要对返回值进行判断。realloc返回的地址有可能不是原来的地址,所以要接受他返回的值,最后不要忘了free。 */
-
使用完动态内存后要free,不然会发生内存泄漏,且一块空间不能释放两次,也不能释放不属于你的空间,但是可以释放一块指向NULL的指针。free完成后要手动将指向这快递至的指针赋空。
-
使用动态内存可以模拟出二维数组的开辟。例如:
int (*p)[4] =(int [3])malloc(3*4*sizeof(int));//这样就开辟了一个三行四列的二维数组。
进程的地址空间
- 栈:存放局部变量和用于函数的调用
- 堆:动态内存在堆上申请,注意堆需要人工管理
- 数据段:数据段分为data段和bss段。data段用来存放初始化的全局变量或者静态变量。bss段用来存放未初始化的全局或者静态变量
- 文本段:将可执行转换的机器语言存放到文本段