c语言struct结构体强制类型转换的实现

 更新时间:2026年01月12日 08:55:43   作者:blog_xu  
本文深入探讨了C语言中结构体的定义、初始化及成员访问,包括无标签和显示标签声明,以及如何通过typedef简化结构体使用,具有一定的参考价值,感兴趣的可以了解一下

一、 关于struct相关说明

1、无结构体标签

	struct {
		int in;
		int out;
	}GPIO_t;

声明了一个无名结构体,并创建了一个结构体变量GPIO_t(已分配空间),该方法只适合创建一个结构体变量

	typedef struct {
		int in;
		int out;
	}GPIO_t;
	/*静态分配内存*/
	GPIO_t GPIOA;
	/*动态分配内存*/
	GPIO_t *GPIOA = (GPIO_t*)malloc(sizeof(GPIO_t));
	free(GPIOA);

使用typedef关键字,可以为结构体GPIO_t创建多个变量,例如:GPIO_t GPIOA,GPIOB;

2、显示声明结构体标签

	struct _GPIO_t{
		int in;
		int out;
	};

如需声明多个结构体变量:struct _GPIO_t GPIOA,GPIOB;

注:常用第二种方法声明创建结构体,具体高级用法请看下面讲解

二、强制类型转换

1、普通数据类型强制转换,使用强制类型转换符

(type_name) expression

例如:

	int sum = 17, count = 5;
	double mean;
	
	mean = (double)sum / count;
	printf("Value of mean : %f \n",mean);

编译运行输出以下结果:

注:这里要注意的是强制类型转换运算符的优先级大于除法,因此 sum 的值首先被转换为 double 型,然后除以 count,得到一个类型为 double 的值

2、数据类型强制转化为结构体类型

#include <stdio.h>

int main (void) {
	
	int a[] = {1,2,'a','b'};
	
	typedef struct _GPIO_t{
		int in;
		int out;
		int type;
		int value;
	}GPIO_t;
	
	GPIO_t *GPIOA = (GPIO_t *) &a;
	/*
	 * 等同于GPIO_t *GPIOA = (GPIO_t *) &a;
	 * 因为数组的首地址为 可以表示为 a,&a,&a[0] 
	*/
	printf("%d \n",GPIOA->in);
	printf("%d \n",GPIOA->out);
	printf("%c \n",GPIOA->type);
	printf("%c \n",GPIOA->value);
		
}

编译运行如何结果:

注:通过该方法可以把某一起始地址的数据类型与结构体成员相对应,以后直接通过结构体成员去访问
结构体成员之间默认32位对齐,在定义成员时需要特别注意

实用举例:

#include <stm32f10x.h>
typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

/*Peripheral base address define*/
#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOA                 ((GPIO_TypeDef *) GPIOA_BASE)

/*函数调用*/
#include "led.c"
void LED_Init(void)
{
	RCC->APB2ENR|=1<<3;    // 使能PORTA时钟
	GPIOA->CRL&=0XFF0FFFFF; 
	GPIOA->CRL|=0X00300000;//PA.5 推挽输出
	GPIOA->ODR|=1<<5;      //PA.5 输出高
}

三、给结构体变量赋值

	GPIO_t GPIOB = {
		.in = 3,
		.out = 4,
		.type = 'A',
		.value = 'B' 
	};
	printf("%d \n",GPIOB.in);
	printf("%d \n",GPIOB.out);
	printf("%c \n",GPIOB.type);
	printf("%c \n",GPIOB.value);

注:callback函数使用时,直接给成员变量赋值

*举例说明结构体成员数据类型对齐问题
1、成员变量字节已经对齐使用

	int a[] = {'abcd',4444};
	typedef struct _GPIO_t{
		char in;
		char out;
		char type;
		char value;
		int data;
	}GPIO_t;
	
	GPIO_t *GPIOA = (GPIO_t *) &a;

	printf("%c \n",GPIOA->in);
	printf("%c \n",GPIOA->out);
	printf("%c \n",GPIOA->type);
	printf("%c \n",GPIOA->value);
	printf("%d \n",GPIOA->data);

编译运行输出结果:

注:数据存储格式分为大小端存储,所以结构引用输出顺序可能不太对应

2、成员变量没有对齐

	int a[] = {1234,5678,'abcd',4444};
	typedef struct _GPIO_t{
		int in;
		int out;
		char type;
		char value;
		int data;		//会自动四字节对齐因此直接指向a[3] 
	}GPIO_t;
	
	GPIO_t *GPIOA = (GPIO_t *) &a;

	printf("%d \n",GPIOA->in);
	printf("%d \n",GPIOA->out);
	printf("%c \n",GPIOA->type);
	printf("%c \n",GPIOA->value);
	printf("%d \n",GPIOA->data);

编译运行结果:

注:因为自动对齐缘故,其中有些数据会自动丢掉

3、成员变量不使用自动给对齐

	int a[] = {1234,5678,'abcd',4444};
	
	/*
	 * ARM系统使用 __packed取消字节对齐 
	*/
	#pragma pack(1)		//强制设置1字节对齐 
	typedef struct _GPIO_t{
		int in;
		int out;
		char type;
		char value;
		int data;		//会自动四字节对齐因此直接指向a[3] 
	} GPIO_t;
	
	GPIO_t *GPIOA = (GPIO_t *) &a;

	printf("%d \n",GPIOA->in);
	printf("%d \n",GPIOA->out);
	printf("%c \n",GPIOA->type);
	printf("%c \n",GPIOA->value);
	printf("%d \n",GPIOA->data);

编译运行结果:

注:最后一个成员由于对齐错误出现乱码

到此这篇关于c语言struct结构体强制类型转换的实现的文章就介绍到这了,更多相关c语言struct结构体强制类型转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c/c++ 利用sscanf进行数据拆分操作

    c/c++ 利用sscanf进行数据拆分操作

    这篇文章主要介绍了c/c++ 利用sscanf进行数据拆分操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Visual Studio Code 配置C、C++ 文件debug调试环境的详细过程

    Visual Studio Code 配置C、C++ 文件debug调试环境的详细过程

    这篇文章主要介绍了Visual Studio Code 配置C、C++ 文件debug调试环境,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • C++语法详解之封装、构造函数、析构函数

    C++语法详解之封装、构造函数、析构函数

    这篇文章主要介绍了C++语法详解之封装、构造函数、析构函数的相关知识,通过实例代码给大家详细介绍,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 简要说明C语言中指针函数与函数指针的区别

    简要说明C语言中指针函数与函数指针的区别

    这篇文章主要介绍了C语言中指针函数与函数指针的区别,指针函数和函数指针是C语言入门学习中的基础知识,需要的朋友可以参考下
    2016-04-04
  • OpenCV 图像金字塔的实现示例

    OpenCV 图像金字塔的实现示例

    本文将结合实例代码,介绍OpenCV 图像金字塔,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • C语言基本排序算法之桶式排序实例

    C语言基本排序算法之桶式排序实例

    这篇文章主要介绍了C语言基本排序算法之桶式排序,简单说明了桶式排序的原理并结合具体实例给出了C语言实现桶式排序算法的具体步骤与相关操作技巧,需要的朋友可以参考下
    2017-09-09
  • Qt中实现多线程导出数据功能的四种方式小结

    Qt中实现多线程导出数据功能的四种方式小结

    在以往的项目开发中,在很多地方用到了多线程,本文将记录下在Qt开发中用到的多线程技术实现方法,以导出指定范围的数字到txt文件为例,展示多线程不同的实现方式
    2025-08-08
  • C语言实现五子棋小游戏

    C语言实现五子棋小游戏

    五子棋游戏是一款很经典的智力游戏,只有学过编程语言的人,把五子棋的编程原理弄懂了,就能用自己熟悉的语言实现出来,在这里给大家分享,c语言五子棋源码,仅供大家参考借鉴。
    2016-03-03
  • Qt 实现钢笔画线效果示例及详细原理

    Qt 实现钢笔画线效果示例及详细原理

    这篇文章主要介绍了Qt 实现钢笔画线效果示例及详细原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • C语言超详细讲解宏与指针的使用

    C语言超详细讲解宏与指针的使用

    宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的替换。要想突破C语言的学习,对指针的掌握是非常重要的,本文将具体针对宏与指针的基础做详尽的介绍
    2022-06-06

最新评论