一、题目描述
二、分析求解
- 指针长度:
64位机器上所有指针类型sizeof = 8
sizeof(ptr) 与指针类型无关
- 指针类型:设置指针类型的目的是
规定指向元素的内存大小
规定指针移动的长度
char* p p++ 移动1B
int* p p++ 移动4B
MyNode *p p++ 移动20B
- 指针类型转换测试
#include <stdio.h>
typedef struct node1{
struct node1 *l1, *r1;
int data;
}MyNode;
typedef struct node2{
struct node2 *l2, *r2;
}BNode;
int main(int argc, char **args)
{
MyNode m;
m.l1 = (struct node1*)0x111;
m.r1 = (struct node1*)0x222;
m.data = 1;
BNode *b = (BNode*)&m;
int *p = (int*)&m;
// 打印 0x111 0x222 1 1
printf("%p %p %d %d\n", *p, *(p+2), *(p+4), *(int*)(b+2));
return 0;
}
- 代码分析:
#include <stdio.h>
void* basic_memset(void *s, int c, size_t n) {
size_t cnt = 0;
unsigned char *schar = (unsigned char *)s;
while (cnt < n) { // 按字节逐个写
*schar++ = (unsigned char) c;
cnt++;
}
return s;
}
void* effective_memset(void *s, unsigned long cs, size_t n) {
size_t K = sizeof(unsigned long);
size_t cnt = 0;
unsigned char *schar = (unsigned char *)s; // 指针类型转换
while (cnt < n) {
// printf("%p %d\n", schar, (size_t)schar);
if ((size_t)schar % K == 0) { // 填充字节使地址对齐为K的倍数
break;
}
*schar++ = (unsigned char)cs; // 逐字节填充
cnt++;
}
unsigned long *slong = (unsigned long *)schar; // 指针类型转换
size_t rest = n - cnt;
size_t loop = rest / K;
size_t tail = rest % K;
for (size_t i = 0; i < loop; i++) {
*slong++ = cs; // 按字写
}
schar = (unsigned char *)slong; // 转换指针类型
for (size_t i = 0; i < tail; i++) { // 填充尾部
*schar++ = (unsigned char)cs;
}
return s;
}
int main()
{
unsigned long a = 0x6161616161616161; // "aaaaaaaa"
int b = 0x41414141; // "AAAA"
int *res = (int*)effective_memset(&b, a, 15);
for (int i = 0; i < 10; i++) {
printf("%p\n", *res++); // 打印15个0x61
}
return 0;
}
-
总结:
第一次写15个0x61 第二次写10个0x61内存依然保留了15个0x61
并没有删除多余的字节 而是新数据覆盖脏内存来使用内存
写不同长度的数据关键是
转换指针的类型 使指针移动不同的长度