C 语言编程 — 结构体的数据类型转换

举报
云物互联 发表于 2021/08/05 23:02:21 2021/08/05
【摘要】 目录 文章目录 目录数组类型强制类型转换为结构体结构体之间的强制类型转换 数组类型强制类型转换为结构体 先看一个例子: #include <stdio.h> int main(void) { unsigned char arr[] = "0123456789abcdefghijk"; struct A { int a; char b;...

目录

数组类型强制类型转换为结构体

先看一个例子:

#include <stdio.h>


int main(void) { unsigned char arr[] = "0123456789abcdefghijk"; struct A { int a; char b; char c; char d; int e; } p, *pp; struct B { int a; char b; int c; }; p.a = 1; p.b = '2'; p.c = '3'; p.d = '4'; p.e = 5; pp = &p; printf("pp->a: %d\npp->b: %c\npp->c: %c\npp->d: %c\npp->e: %d\n", pp->a, pp->b, pp->c, pp->d, pp->e); printf("**********\n"); pp = (struct A *)arr; printf("pp->a: %d\npp->b: %c\npp->c: %c\npp->d: %c\npp->e: %d\n", pp->a, pp->b, pp->c, pp->d, pp->e); return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

运行结果:

pp->a: 1
pp->b: 2
pp->c: 3
pp->d: 4
pp->e: 5
**********
pp->a: 858927408
pp->b: 4
pp->c: 5
pp->d: 6
pp->e: 1650538808

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

上述是一个将数组类型变量强制类型转换为 struct A 的例子,结合结构体内存分布的内容我们可以看出:结构体数据类型转换的本质就是对结构体内存空间的填充。通过这种方式,可以把某一起始地址的数据类型与结构体成员相对应。

结构体之间的强制类型转换

要理解结构体之间的强制类型转换,需要明白以下几点原理:

  1. 结构体变量是如何分布内存的。
  2. 结构体变量的内存首地址。
  3. 结构体成员在结构体内存中的偏移地址。

实际上在上述的内容中,我们已经提到了这 3 点内容。

先看一个例子:

#include <stdio.h>


struct A { int x; char y;
} a, *pa;

struct B { char x; int y;
} b, *pb;

int main(void) { a.x = 1; a.y = 'A'; pa = &a; printf("pa->x: %d, pa->y: %c\n", pa->x, pa->y); b.x = 'A'; b.y = 1; pb = &b; printf("pb->x: %c, pb->y: %d\n", pb->x, pb->y); struct B z; z.x = ((struct B *)pa)->x; printf("z.x: %c, z.y: %d\n", z.x, z.y);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

输出结果:

pa->x: 1, pa->y: A
pb->x: A, pb->y: 1
z.x: , z.y: 32766

  
 
  • 1
  • 2
  • 3

上述例子为结构体之间的强制类型转换,根据结构体内存分布的内容,并且我们暂不考虑内存对齐的话,我们知道:

  • a 的内存分布为:前 4B,后 1B
  • b 的内存分配为:前 1B,后 4B

当我们执行强制类型转换时,本质是就是 C 语言会对结构体变量 a 的空间,按照 struct B 的布局进行解释:也就是说,将 a 的第一个字节看成 struct B 的第一个成员,且按 ASCII 码处理数据,而将后面的 4B 看成 struct B 的第二个成员,并按补码格式解释数据。

需要注意的是,C 语言中的结构体强制类型转换本质是对指针进行转换,所以转换的对象必须为一个指针类型:

struct str1 a;

struct str2 b;
a = (struct str1)b; 	 // this is wrong
a = ((struct str1)&b);	 // this is correct

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

通过数组强制类型转换为结构体以及结构体之间互相转换的内容,我们可以总结到:C 语言中结构体变量之间直接的赋值和转换本质是将右值的内存数据直接覆盖到左值所占用内存空间中,然后再根据 C 语言对这块内存的理解(类型定义)表达出来

struct in_addr {
	unsigned long a_addr;
}

struct sockaddr_in {
	unsigned short sin_family; // 地址类型(2B)
	unsigned short int  sin_port; // 端口号(2B)
	struct in_addr sin_addr; // IP 地址(4B)
	unsigned char sin_zero[8]; 	// 填充空间(8B)
}

struct sockaddr { unsigned short  sa_family;	// 地址类型(2B) char sa_data[14];	// 协议地址(14B)
 }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在实际的网络编程中,通常会先初始化 sockaddr_in,再将它强制转化成 sockaddr 来使用。这两个结构体,长度都为 16 字节,sockaddr_in.sin_family 的数据存入 sockaddr.sa_family,剩下的 14 个字节存入 sockaddr.sa_data,这样在各种操作中可以方便的处理端口号和 IP 地址。

文章来源: is-cloud.blog.csdn.net,作者:范桂飓,版权归原作者所有,如需转载,请联系作者。

原文链接:is-cloud.blog.csdn.net/article/details/106962556

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。