c语言_Day35_08_06
1、内存函数
1. memmove
memcpy无法处理重叠拷贝,而memmove用于处理重叠拷贝
int main()
{
int arr[10] = { 1, 2, 3, 4 };
memmove(arr + 2, arr, 30);
return 0;
} 实现:void* my_memmove(void* des, void* src, int size)
{
assert(des && src);
// 从后向前拷贝
if (des > src)
{
char* src_p = (char*)src + size;
char* des_p = (char*)des + size;
for (int i = 0; i < size; i++)
{
*--des_p = *--src_p;
}
}
// 从前向后拷贝
else
{
for (int i = 0; i < size; i++)
{
*((char*)des)++ = *((char*)src)++;
}
}
return des;
} 2. memcmp
比较数据内存大小比较大小,原理同strcmp
3. memset
内存设置:对目标对象的内存空间设定指定值
参数:
void des:目标对象
int val:目标设置值
size_t size:待设置的大小
返回值:目标对象
int main()
{
char arr[5] = { 0 };
memset(arr, '#', 4);
printf("%s\n", arr);
return 0;
} 注:参数size指内存字节大小,而非元素个数
2、自定义类型
由于c语言的内置类型无法完全满足需求,故引入自定义类型
自定义类型包括:结构体、枚举、联合体
1. 结构体基础
结构体:一些值(成员变量)的集合,成员的类型可以不同int main()
{
struct Student
{
char name[20];
int age;
}s;
struct Student stu = { "Tom", 18 };
printf("%s %d\n", stu.name, stu.age);
return 0;
} 注:结构体自引用时应定义结构体指针成员,而非结构体成员
struct Node
{
int data;
struct Node next;
};
int main()
{
printf("%d\n", sizeof(struct Node));
return 0;
} 结构体初始化:
struct Student stu = {"Tom", 18}; 结构体成员访问:
结构体变量访问成员
结构体指针访问成员
2. 结构体类型对齐
- 第一个成员在与结构体变量偏移量为0的地址值
- 其他成员变量要对齐到对齐数的整数倍的地址处
对齐数 = 编译器默认的对齐数 与 该成员大小的较小值
vs默认对齐数为8
struct S1
{
char c1;
int a;
char c2;
}s1;
struct S2
{
char c1;
char c2;
int a;
}s2;
int main()
{
printf("%d\n", sizeof s1);
printf("%d\n", sizeof s2);
return 0;
}
内存对齐的意义:
- 平台因素:并非所有的硬件平台都能访问任意地址上的任何数据,若所以访问可能抛出硬件异常
- 性能因素:数据结构(尤其是栈)应尽可能在自然边界上对齐,因为访问未对齐的内存CPU需访问两次,而对齐的内存仅访问一次
结论:让占用空间小的成员集中在一起
补:默认对齐数的修改
通过预处理指令 #pragma 以更改默认对齐数int main()
{
#pragma pack(1)
struct S
{
char c;
int a;
}s;
printf("%d\n", sizeof s);
#pragma pack()
return 0;
}
|