直接使用c, 有个好处, 自己可以完全控制内存啊,一切脑海中记住内存及指针, 就很容易知道操作是怎样.
1. 分配一段内存, 这段内存使用什么样的指针操作, 那么对应就是多少字节的操作, 也就是说, 看你怎么去解释
这块内存了.
例如, 若分配给一个10个字节的类型, 如果用一个int类型的指针指向这块内存, 那么一次操作, 就是int的字节的大小, 如果一个struct指向这块内存, 那么一次操作就是针对这个struct的内存的大小, 如果是一个数组指向这块内存, 那么就是连续的这个数组的元素类型的字节了.
2. 怎么改变内存中指针的指向, 进行指针的加减就行了, 但是指针加减, 这个和指针的类型有关系的.
#include <stdio.h> #include <stdlib.h> typedef struct { int i; char c; } tag; int main(void) { tag *t = (tag *)malloc(20); tag *t2 = t+1; printf("%d\n", sizeof(tag)); printf("%p\n", t); printf("%p\n",t2); return EXIT_SUCCESS; }
上述代码的打印结果:
8
001A3D10
001A3D18
3. struct存在对齐问题, 所以上述示例的的struct的实际大小不是5, 而是8
4. 怎么实现变长数组? 示例:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int i; char c[0]; } tag; int main(void) { tag *t = (tag *)malloc(13); printf("%d\n", sizeof(tag)); t->i=4; memcpy(t->c,"hijimmee", 8); t->c[8]='\0'; printf("%s\n",t->c); free(t); return EXIT_SUCCESS; }
更具体的例子:
#include <stdlib.h> #include <stdio.h> typedef unsigned long cell; /* INSTANCE */ struct instanceStruct { // 这里的数组仅仅是占位, data[]数组不仅仅只有一个元素, 可以使用更大的index值来存取 // data[1]之后的元素值 union { cell *cellp; cell cell; } data[1]; }; struct instance { int num; int arr[2]; }; int main(void) { int size = sizeof(cell) * 3; printf("%d\n", size); printf("%lu\n", sizeof(instanceStruct)); instanceStruct *ins = (instanceStruct *) malloc(size); cell *c = (cell *)malloc(sizeof(cell)); ins->data[0].cell = 5; ins->data[1].cell = 15; ins->data[2].cell = 155; *c = 157; printf("%lu,%lu,%lu, %lu\n", ins->data[0].cell, ins->data[1].cell, ins->data[2].cell); printf("%d\n", sizeof(instance)); instance *s = (instance *) malloc(sizeof(instance) * 2); s->num = 1; s->arr[0] = 2; s->arr[1] = 3; instance *first = s; s++; s->num = 4; s->arr[1] = 5; s->arr[2] = 6; printf("%d, %d, %d\n", first->num, first->arr[0], first->arr[1]); printf("%d, %d, %d\n", s->num, s->arr[0], s->arr[1]); // 这里可以看到,实际上不管是否数组是否越界了,永远根据指针类型进行访问 printf("overflow access: %d\n", first->arr[2]); }
我64位的机器,输出结果如下:
24 8 5,15,155, 12 12 1, 2, 3 4, 13, 5 overflow access: 4