当前位置:网站首页>[Essence] Analysis of the special case of C language structure: structure pointer / basic data type pointer, pointing to other structures

[Essence] Analysis of the special case of C language structure: structure pointer / basic data type pointer, pointing to other structures

2022-08-09 11:25:00 XV_

参考链接:Structure pointer pointing to different structure instance
注:You can view the question and the only response to this post,that is relatively correct,不要看comment,有很多错误.

I refuse to analyze this problem,Because no one seems to use it like that,但是……The compilation principle example code of the health care teacher in China andLinux0.11内核中,I came across such an amazing code,那就I have to research it!Write the code is, after all, a great god,I don't know if it's me.

1 测试代码

#include <stdio.h>
#include <stdlib.h>

struct A {
    
	char a;
	int b;
};

struct B {
    
	int c;
	int d;
};

struct C {
    
	int e;
	char f;
};



int main() {
    
	struct A a = {
     'a', 100 };
	struct B b = {
     101, 300 };
	struct C c = {
     200,'c' };

	// 根据字节对齐,都占据8字节
	printf("A: size %d %c %d\n", sizeof(a), a.a, a.b);
	printf("B: size %d %d %d\n", sizeof(b), b.c, b.d);
	printf("C: size %d %d %c\n", sizeof(c), c.e, c.f);


	struct A *ap = &b; // A结构体指针,指向结构体B
	printf("%d %d\n",ap->a, ap->b);
	printf("%c %d\n", ap->a, ap->b);

	char *chp = &b;
	chp[1] = 'b';  // This area is actually free space caused by byte alignment
	printf("%d %d\n", ap->a, ap->b);
	printf("%c %d\n", ap->a, ap->b);

	/* How to access the memory,取决于ap指针,How much can you visit,depends on the memory area itself */
	ap->a = 'c';  // ap->a = 'c'就是相当于 char a = 'c';
	ap->a = 1000; // ap->a = 1000 就是相当于 char a = 1000; 1000Excessive assembly is truncated high
	ap->b = 3000; // ap->b <=> int b ...

	struct C *cp = &b; // C结构体指针,指向结构体B
	printf("%d %d\n", cp->e, cp->f);
	printf("%d %c\n", cp->e, cp->f);

	cp->e = 3000;
	cp->f = 'e';
	cp->f = 1000;
	

	// Integer pointer to structureA
	int *bp = &a;
	bp[0] = 1000;
	bp[1] = 2000;
	printf("A: %c %d\n", a.a, a.b);
	printf("A: %d %d\n", a.a, a.b);
	bp[2] = 2000;	// memory can be modified,But the stack overflow,
						// because the space is not allocated(局部变量是保存在堆栈中的)

	return 0;
}

2 The problem of the space occupied by the structure & 字节对齐

struct A {
    
	char a;
	int b;
};

struct B {
    
	int c;
	int d;
};

struct C {
    
	int e;
	char f;
};

...
struct A a = {
     'a', 100 };
struct B b = {
     101, 300 };
struct C c = {
     200,'c' };

// 根据字节对齐,都占据8字节
printf("A: size %d %c %d\n", sizeof(a), a.a, a.b);
printf("B: size %d %d %d\n", sizeof(b), b.c, b.d);
printf("C: size %d %d %c\n", sizeof(c), c.e, c.f);
...

运行以上程序,我们可以直到,Each of the three structures creates a variable,And the size of the space occupied by each structure is8字节.

在这里插入图片描述
至于为什么都是8字节,This is a memory alignment issue,不展开说明了,Let's look at these structuresAllocated space.

在这里插入图片描述

  • Each structure occupies8字节的内存空间
  • The red part represents the actual occupied space
  • 蓝色部分表示空闲空间

注意:这就意味着,whatever is assigned8字节空间,是可以任意访问的,Access is not allowed outside the space.

让结构体A的指针ap,指向结构体B的变量b

Now we create a structA的指针,让其指向b.

struct A *ap = &b; // A结构体指针,指向结构体B
printf("%d %d\n",ap->a, ap->b);
printf("%c %d\n", ap->a, ap->b);

在这里插入图片描述
Let's look at the memory,To analyze the printing results.

在这里插入图片描述

The above is the distribution of memory,现在

  • 访问ap->a打印出来的是:101,e
  • 访问ap->b打印出来的是300

所以apThe actual access of the pointer should be the part highlighted below:
在这里插入图片描述

而这部分,是不是很熟悉?
在这里插入图片描述

所以,appointers despite pointing to structsB,但是Actually according to the structureA的结构访问内存.

2.1 使用char指针指向结构体B

刚才我们发现,使用结构体A的指针,Can directly access structureB,那么,If it is the basic data types?我们试一下.

char *chp = &b;
chp[1] = 'b';  // This area is actually free space caused by byte alignment
printf("%d %d\n", ap->a, ap->b);
printf("%c %d\n", ap->a, ap->b);

在这里插入图片描述
We see the memory distribution as shown above,现在执行chp[1] = 'b'(b的ASCII码是62)

之后就变成了:

在这里插入图片描述

哦!这是令人惊讶的,charA pointer of type points to a memory area,Then use the subscript to modify the value of the memory!

Remember dynamic array to apply for?Same principle as inside!

int *a = (int *)malloc(sizeof(int) * 10);
a[0] = 1; // 使用下标访问
a[1] = 2;
...
free(a);

告诉我们两件事

  1. The pointer points to the first element by default,索引是0
  2. Use subscript indices have access to the back of the elements in turn,The amount of memory to move backwards each time,Depends on the data type of the pointer

So the above is not difficult to understand.

Then we continue with the program

printf("%d %d\n", ap->a, ap->b);
printf("%c %d\n", ap->a, ap->b);

在这里插入图片描述

尽管之前的空闲空间改变了,But the results remain the same,That is to say we are right in saying that before.

在这里插入图片描述

再进一步验证

/* How to access the memory,取决于ap指针,How much can you visit,depends on the memory area itself */
ap->a = 'c';  // ap->a = 'c'就是相当于 char a = 'c';
ap->a = 1000; // ap->a = 1000 就是相当于 char a = 1000; 1000Excessive assembly is truncated high
ap->b = 3000; // ap->b <=> int b ...

结果显而易见,对于ap->a = 1000,尽管1000已经超过了1字节大小,But in the end only the first byte is modified,这就好比char a = 1000一样,a = 0xe8

在这里插入图片描述

是的,1000 = 0x3e8,但是只有一个字节,所以最高位的3被舍弃了.

2.2 用结构体C指针cp指向结构体B

struct C *cp = &b; // C结构体指针,指向结构体B
printf("%d %d\n", cp->e, cp->f);
printf("%d %c\n", cp->e, cp->f);

cp->e = 3000;
cp->f = 'e';
cp->f = 1000;

我们再试一试!

最终结果显而易见.

在这里插入图片描述
在这里插入图片描述

2.3 用int指针指向结构体A

// Integer pointer to structureA
int *bp = &a;
bp[0] = 1000;
bp[1] = 2000;
printf("A: %c %d\n", a.a, a.b);
printf("A: %d %d\n", a.a, a.b);
bp[2] = 2000;	// memory can be modified,But the stack overflow,
					// because the space is not allocated(局部变量是保存在堆栈中的)

Actually, we've done this before,之前用char,现在用intdo it again.

在这里插入图片描述

What does this show further??

  1. a提供了有限的8字节内存空间
  2. bpwhere the pointer can be modified,depends on the address it points to;How much space to modify at one time,depends on the size of its data type
  3. Pointers cannot modify unallocated space,最后bp[2]visited outside space,因此产生了
    在这里插入图片描述

Because local variables are allocated on the stack,Now this local variable access is out of bounds,产生了错误,栈被破坏.

Stack corruption is very complicated here,First, it is roughly understood as,Error using unallocated space.

Linux0.11 内核中,使用上述方法,实现了GDT和IDT.

3 小结:The essence here

分析了这么多,Finally a summary.

There are only two things in our eyes

  • The allocated memory space
  • pointer to a data type

现在,我们就让The pointer points to the starting address of the memory space,Then you can operate this memory space.

add some more restrictions

  • Memory space is so big,no access outside
  • The address of each access by the pointer,Is accessed through the subscript,Only integer multiples of the size of the data type can be moved at a time

在这里插入图片描述

At this time in your eyesC语言,分配一块内存,再创建一个指针,打遍天下无敌手!

当然了,No one does this except in special circumstances.,你会疯掉,People who read your code will go crazy!

4 补充:Go straight to the bottom,看汇编代码

Our previous analysis was based onClanguage level,比较抽象,实际上,Assembly language after compilation,一看就明白了.
在这里插入图片描述

你可以看到ap->a直接访问的是byte,而ap->b访问的是dword,一个是字节,one is double word,Natural and clear size.

这也是编译器的功能,把C语言提供的,Lots of abstractions for human convenience,Convenient to translated into machine using a small amount of complex combination of instruction.

5 What does it mean to be invincible all over the world??

Actually just kidding.……But it can be done!我们试一试.

int main() {
    

	char aaa[4] = {
     1,2,3,4 };
	char aaa2[4] = {
     1,2,3,4 };
	int *bbb = &aaa;
	printf("\n\n%x\n\n\n", bbb[0]);
	
	return 0;
}

会打印什么呢?显而易见的!内存是01 02 03 04,然后一个int *pointer accesses it,打印04030201.

在这里插入图片描述

我们可以使用bbb[0]或者*b都行,因为b指向起始地址.

那,能不能通过bbb[1]访问aaa2的内存呢?

不行! 因为aaa1aaa2are two array variables,Their position in the memory is not continuous,是随机的,If you want to achieve the inner seed effect,那就是前面提到的结构体了,Put these two into a struct,It just allocates memory continuously.,就能使用bbb[1]了.


最后,Remember that only two things

  • A piece of allocated memory
  • 一个指针
原网站

版权声明
本文为[XV_]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/221/202208091103199012.html