欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c内存操作感悟(1)

程序员文章站 2022-07-04 08:09:16
...

直接使用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