数据类型
基本数据类型
变量所占大小
X64 | X86 | |
---|---|---|
char | 1字节 | 1字节 |
short | 2字节 | 2字节 |
int | 4字节 | 4字节 |
long | 8字节 | 4字节 |
long long | 8字节 | 8字节 |
float | 4字节 | 4字节 |
double | 8字节 | 8字节 |
long double | 通常16字节 | 通常8字节 |
char
分为三类型:
1.char:标准类型
2.unsigned char:无符号char(0~255)
3.signed char:有符号char(-128~127)
构造类型
数组
1.一维数组
字符串/字符数组
char arr1[] = "hello"; 字符串:结尾有'\0'终止符,arr1占6字节
char arr2[] = {'H', 'e', 'l', 'l', 'o'}; 字符数组:结尾无'\0',arr2占5字节
'\0'影响printf等输出,输出结果为'\0'之前
字符串的申明方式
1.静态分配,编译时在栈上分配好内存
2.字符串常量
3.动态分配内存(malloc和new)
4.自动分配,在局部函数中
操作函数
size_t strlen(const char *str) 返回字符串长度,不包含'\0'
char *strcpy(char *dest, char *src) 把src复制给dest
char *strncpy(char *dest, const char *src, size_t n) 把src复制给dest前n个字符
char *strcat(char *dest, const char *src) 把src添加到dest的结尾
char *strncat(char *dest, const char *src, size_t n) 把src前n个字符添加到dest结尾
int strcmp(const char *str1, const char *str2) 比较字符串是否相同,成功返回0,失败返回不同个数
int strncmp(const char *str1, const char *str2, size_t n) 比较前n个字符串,返回与strcmp相同
char *strchr(const char *str, int c) 返回c第一次在str出现的地址
char *strrchr(const char *str, int c) 返回c最后一次在str出现的地址
char *strstr(const char *haystack, const char *needle) 返回needle在haystack第一次出现的地址
地址
char arr[10] = "Hello";
arr与&arr[0]所表示是一样的
&arr是整个数组的地址,类型是char (*)[10],表示10个指向char元素的指针
指针数组与数组指针
指针数组,包含3个char的指针
char *ptr_arry[3]
数组指针,指向一个包含3个char的数组
char (*arry_ptr)[3]
2.二维数组
初始化
1.没什么好说的
int array[3][4];
2.编译器自动分配
int array[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
3.分配动态内存
int rows = 3;
int cols = 4;
int **array = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
array[i] = (int *)malloc(cols * sizeof(int));
}
4.使用stl容器
int rows = 3;
int cols = 4;
std::vector<std::vector<int>> array(rows, std::vector<int>(cols));
地址
&a[1],&a[0]==a;一维数组地址
&a[0][1],&a[0][0] == a[0];元素地址
&a;二维数组地址
结构体
声明
1.默认声明
struct Point {
int x;
int y;
};
C++的结构体class,为兼容c,保留了struct
2.定义并声明实例
struct Point {
int x;
int y;
} p1, p2;
3.结构体别名
typedef struct {
int x;
int y;
} Point;
Point p1;
C++默认声明,创建实例时不需要声明结构体struct或class
结构体大小
struct Example {
char a; // 1 byte
int b; // 4 bytes
char c; // 1 byte
};
以上面为例,变量存储地址为自身所占字节大小的倍数,设从0x00开始,char占1个字节,地址在0x00,b占4字节,因为地址要是自身字节大小的整数倍,所以地址在0x04;c占1个字节,地址在0x08,所以Example结构体的大小为9字节。
其中,c特有的位域,变量+:+位数,用于修改变量大小,节省内存空间。计算方式为同类型变量合并,不足该变量字节大小的部分自动填充,不同类型的变量按结构体的计算方式存入地址。
链表
单链表:简单,节点只包含指向下一个节点的指针。
双向链表:支持双向遍历,节点包含指向前一个和下一个节点的指针。
循环链表:尾节点指向头节点,形成一个环,适合需要循环访问的情况。
C++中class与struct区别
(1)相同点
都能拥有成员函数,公有和私有部分;class可以实现的struct也可以实现。
(2)不同点
struct默认公有,class默认私有;struct默认公有继承,class默认私有继承。
(3)C++的struct与C的区别
C语言中struct是自定义数据类型;C++中是抽象数据类型,支持成员函数的定义(C++中可以继承和实现多态)
C语言中struct没有访问权限设置,成员只能是变量,但可以存入函数地址,数据不能被隐藏。
C++设置了访问权限,功能与class一样,默认是public访问。
C语言声明实例时必须在前面加struct,除非定义结构体时使用typedef。C++不需要,结构体struct在C++中被当作特例。
联合体
联合体声明
union Data {
int i;
float f;
char str[20];
};
联合体大小计算
联合体的大小是其最大的数据成员大小的整数倍再满足编译器的内存对齐要求的最小倍数。以上面为例,联合体最大成员时char str[20],则联合体大小为20字节,若内存对齐要求为4字节,则不变;若为8字节,则填充4字节为24字节。
判断大小端
#include <iostream>
union data{
int a;
char b;
}
void main()
{
data udata;
udata.a = 0x12345678;
if(udata.b == 0x78)
printf("Little-Endian\n");
else if(udata.b == 0x12)
printf("Big-Endian\n");
else
printf("Unkonwn Endian\n");
}
指针
内存的申请与释放
C++中的new
分配内存,构造一个整数
int* ptr = new int;
分配内存,构造函数参数进行构造
MyClass* ptr = new MyClass(arg1, arg2);
分配数组内存
MyClass* array = new MyClass[5];
或者memset设置内存初始值
使用std::nothrow,new失败时返回null
malloc
type p = (type)malloc(分配大小)
分配失败时返回null
malloc与new的异同
相同点
都可以动态申请内存
不同点
new是C++操作符,支持重载,还会调用构造函数;malloc是C/C++的标准函数。
new是类型安全的,malloc不安全。
new返回具体指针,malloc返回void型指针,需要类型转换。
new自动计算分配内存大小,malloc需要手动计算。
new是封装了malloc。
C++中的delete
释放内存
释放单个对象的内存
MyClass* obj = new MyClass(); // 用 new 分配对象
delete obj; // 释放分配的对象内存
释放数组的内存
MyClass* array = new MyClass[10]; // 用 new[] 分配对象数组
delete[] array; // 释放分配的数组内存
一个new对应一个delete
释放内存后需要将指针指向空
delete null是安全的
free
释放内存
int *array = (int *)malloc(10 * sizeof(int));
free(array);
一个malloc对应一个free
内存释放后将指针指向null,避免产生野指针
free(NULL)会崩溃
new和delete是如何实现的
new的实现过程:调用operator new函数,分配足够大的原始为类型化的内存,以保存指定类型的对象,运行该类型的构造函数,用指定初始化构造函数,最后返回指向新分配的构造后的对象的指针。
delete的实现过程:对指针指向的对象运行析构函数,再用operator delete函数释放对象所使用内存。
被free回收的内存是立即还给操作系统了吗
不是的,被free回收的内存会用双链表ptmalloc保存,当下次申请内存的时候就尝试再内存中寻找合适的返回,避免反复的系统调用,同时tpmalloc也会尝试合并小块内存,防止产生过多内存碎片。