C语言之 .struct结构体,enum枚举,union共用体,以及相互嵌套的使用

一、结构体,枚举,共用体

1、结构体的定义,结构体类似数组,一段连续的地址空间,定义后,空间大小不可更改,但是比数组不同的是,结构体数据类型,可以都不一样,可以定义任何类型,嵌套各种指针。

struct pnode {
	unsigned int sn;
	NODEINFO nodeinfo;
	BOOL loop;
	struct pnode *next;
	struct pnode *previous;
};

typedef struct {   //  typedef 重命名一个结构体类型,结构体大多数是这么用,
	struct pnode *head;
	struct pnode *tail;
	struct pnode *cur;
	WORD mode;
	WORD MaxFile;
} list_info ,*_p_list_info ;
list_info  my_list_info ;   //定义一个list_info 类型的 结构体
_p_list_info  p_list_info;  //定义一个结构体指针
p_list_info   = &my_list_info;  //指向这个结构体

结构体赋值,结构体数组,成员赋值

typedef struct {
	WORD menu_id;
	const WORD* icon;
	BYTE val;
	next_menu next;
	menu_title title;
	BOOL corr_sys_paras;
}menu_format;

menu_format const menu_app_photocap[] = {//在定义结构体变量时,可以这样全部成员赋值
	{
		.menu_id = MENU_ID_PHOTOCAP_SET,
		.icon = (WORD*)IconMenuPhotoCap,
		.next.menu = menu_photocap_item,
		.next.menu_size = sizeof(menu_photocap_item)/sizeof(menu_recorder_item[0]),
		.title.icon_str_id = ICON_ST_PHOTOCAP,
	},
	{
		.menu_id = MENU_ID_SYS_SET,
		.icon = (WORD*)IconMenuSetup,
		.next.menu = menu_sys_item,
		.next.menu_size = sizeof(menu_sys_item)/sizeof(menu_sys_item[0]),
		.title.icon_str_id = ICON_ST_SYS_SET,
	},
};

在定义结构体变量时,可以这样全部成员赋值,和数组一样,定义后,使用时,不能全部一起赋值,需要一个一个成员赋值,a[1] = b[1],


    SX_S8 * pszSendBuf = (SX_S8 *)malloc( UDP_MAX_LEN );//申请一大段内存
	memset(pszSendBuf,0,UDP_MAX_LEN);
	PT_DataPkt_1 pkt 	= (PT_DataPkt_1)(pszSendBuf);  //将这段内存,强制类型转换成结构体类型,按结构体来解析
	
	pkt->u32Sync 		= PKT_SYNC;
	pkt->u8Cmd 			= CMD_ACK_BIT1;
	pkt->u32DataLen 	        = sizeof(T_BIT_1);
	pkt->u32totalPktNum	= 1;
	pkt->u32currretPkt	        = 1;
	pkt->CRC32 			= 0xC4C3C2C1;

	//file data
	memset((SX_U8 *)(&pkt->BITData), 0, sizeof(T_BIT_1) );
	pkt->BITData.u8head 		        = 12;
	pkt->BITData.u8SoftwareRev	= (SX_U8)software_reversion;
	pkt->BITData.u8reserv0 		= 0;
	pkt->BITData.u8reserv1 		= 0;
	pkt->BITData.u8devicetype		= (SX_U8)U8DeviceType;
	pkt->BITData.u8devicestatus	= (SX_U8)client_fpga_status;
	pkt->BITData.u16packnum		= u16packnum;
	memset( pkt->BITData.u8reserver2, 0, sizeof(pkt->BITData.u8reserver2) );
	
	ret = Bit_Server_Send1(handle->ptClientBIT1, (SX_S8 *)pkt, sizeof(T_DataPkt_1));//将结构体,类型强制成一个字节,通过网络发送出去,发送字符时,都一个一个字节传送,对方收到时,用结构体类型,解析,就可以还原了
SX_S32 Bit_Server_Send1(PT_CLIENT handle, void *buf, SX_S32 len)
{
	if( handle == NULL || len <= 0 || len > UDP_MAX_LEN )
	{
		TRACE(DL_ERROR, "DL_ERROR\n");
		return 0;
	}
	
	SX_S32 length;
	if( buf )
	{
		length = MIN(len, UDP_MAX_LEN);
		return sendto( handle->sockfd, (const SX_S8 *)buf, length, 0, (struct sockaddr *)&(handle->cliaddr2),    		sizeof(handle->cliaddr2) );
	}
}

2、枚举enum,将所有的值,列举出来,比如,各种可以操作的id,返回给系统

定义一个enum变量的,规则
enum myenum{
aaa,
bbb,
ccc
}
enum myenum my_num ;

枚举变量,占用4个字节,有的是占用8个字节,字符串常量,分配在特定区域,定义枚举是,就是一个指针变量,在编译,将代码里枚举出来的,字符串,全部进行替换,0,1,2,3,4,,,定义的枚举,变量,绑定到一个起始地址,这个地址,存放,1.2.3.4.5,6.,而不是下面这些字符串,这只是给人看的,这个地址可以很长,向数组一样,看初始化的值了,如果是655536,一个就是int型,10个,就需要10个int型

typedef enum {
	MENU_ID_NONE = 0,  //系统默认第一个是0,其他是1,2。。。,也可以自己定义,随便一个数
	MENU_ID_REC_SET,
	MENU_ID_PHOTOCAP_SET,
	MENU_ID_PLAYBACK_SET,
	MENU_ID_SYS_SET,
	MENU_ID_WIFI_ID,
	MENU_ID_WIFI_PASSWORD,
}enum

第一种,是枚举,进行配置,在不同项目,可以值修改enum的配置初始值,

typedef enum {
	UDP_PORT_LOCAL	= 10001,
	UDP_PORT_BIT2	= 10002,
	UDP_PORT_CFG	= 10003,
}E_UDP_PORT;

typedef enum {
	VIDEO_BITRATE_500K = 0,
	VIDEO_BITRATE_1M	= 1,
	VIDEO_BITRATE_2M	= 2,
	VIDEO_BITRATE_3M	= 3,
	VIDEO_BITRATE_4M	= 4,
	VIDEO_BITRATE_5M	= 5,
}E_VIDEO_BITRATE;

typedef enum {
	SW_OFF	= 0,
	SW_ON= 1,
}E_SW;
menu_format const menu_app_recorder[] = {
#ifndef LCD_320_240
	{
		.menu_id = MENU_ID_REC_SET, //进行赋值配置
		.icon = (WORD*)IconMenuSetup,
		.next.menu = menu_DVR_item,
		.next.menu_size = sizeof(menu_DVR_item)/sizeof(menu_DVR_item[0]),
		.title.icon_str_id = NULL,
	},
#else
	{
		.menu_id = MENU_ID_REC_SET,  //进行赋值
		.icon = (WORD*)IconMenuRecorder,
		.next.menu = menu_DVR_320_240_item,
		.next.menu_size = sizeof(menu_DVR_320_240_item)/sizeof(menu_DVR_320_240_item[0]),
		.title.icon_str_id = ICON_ST_RECORDER,
	},
#endif

第二种是根据枚举返回的,状态,选择对应操作

state = 
switch(state) {
	default:
	case 0:
		pTireIcon = IconTpmsTireFull;
		break;
	case 1:
		pTireIcon = IconTpmsTireOverflow;
		break;
	case 2:
		pTireIcon = IconTpmsTireLow85;
		break;
	case 3:
		pTireIcon = IconTpmsTireLow75;
		break;
	case 4:
		pTireIcon = IconTpmsTireLow50;
		break;
	case 5:

3、共用体 union,所有变量,共用一块内存地址,用其中一个字节最大的成员,进行分配地址,之所以共用,是不知道数据类型,char,int,double都可以用,强制类型转换,就可以接受各种数据类型了,
定义规则
union myunion {

}
union myunion dat_union

typedef union MediumEmifHead	//struct
{
    struct{
        char u8Cmd;
        long long LenH;
    }BITS;
    int    s32Value;
    long long LenH;
    char u8LenH[13];
}T_MediumEmifHead, *PT_MediumEmifHead;

最大的是结构体,所以这个union的大小,就是结构体大小,16个字节

三、嵌套

typedef struct {
    combo_dev_t         devno;              /* device number */
    input_mode_t        input_mode;         /* input mode: MIPI/LVDS/SUBLVDS/HISPI/DC */
    mipi_data_rate_t    data_rate;
	/* MIPI Rx device crop area (corresponding to the oringnal sensor input image size) */
    img_rect_t          img_rect;

    union {
        mipi_dev_attr_t     mipi_attr;
        lvds_dev_attr_t     lvds_attr;
        slvs_dev_attr_t     slvs_attr;
        lvds_dev_attr_ex_t  lvds_attr_ex;
    };
} combo_dev_attr_t;

typedef struct {
    data_type_t           input_data_type;          /* data type: 8/10/12/14/16 bit */
    mipi_wdr_mode_t       wdr_mode;                 /* MIPI WDR mode */
    short                 lane_id[MIPI_LANE_NUM];   /* lane_id: -1 - disable */

    union {
        short data_type[WDR_VC_NUM];               数据也可以枚举,不用事先定义大小,
    };
} mipi_dev_attr_t;


combo_dev_attr_t MIPI_1lane_CHN0_ADV7280AWBCPZ_M_NOWDR_ATTR =
{
    .devno = 0,
    .input_mode = INPUT_MODE_MIPI,
    .data_rate = MIPI_DATA_RATE_X1,
    .img_rect = {0, 0, 720, 576},
 
    {
        .mipi_attr =
        {
            DATA_TYPE_YUV422_8BIT, 	//DATA_TYPE_YUV422_8BIT,	//DATA_TYPE_YUV420_8BIT_NORMAL	DATA_TYPE_RAW_8BIT
            HI_MIPI_WDR_MODE_NONE,
            {0, -1, -1, -1, -1, -1, -1, -1}
        }
    }
};


**四、模仿 linux驱动代码,结构体,实现面向对象**

```c
struct wm8350_gpio_data {
	struct wm8350 *wm8350;
	struct gpio_chip gpio_chip;
};

static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
{
	return container_of(chip, struct wm8350_gpio_data, gpio_chip);
}

static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
	struct wm8350 *wm8350 = wm8350_gpio->wm8350;

	return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
			       1 << offset);
}

static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
	int ret;

	ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
	if (ret < 0)
		return ret;

	if (ret & (1 << offset))
		return 1;
	else
		return 0;
}

static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
	struct wm8350 *wm8350 = wm8350_gpio->wm8350;

	if (value)
		wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
	else
		wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
}

static int wm8350_gpio_direction_out(struct gpio_chip *chip,
				     unsigned offset, int value)
{
	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
	int ret;

	ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
				1 << offset);
	if (ret < 0)
		return ret;

	/* Don't have an atomic direction/value setup */
	wm8350_gpio_set(chip, offset, value);

	return 0;
}

static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
	struct wm8350 *wm8350 = wm8350_gpio->wm8350;

	if (!wm8350->irq_base)
		return -EINVAL;

	return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
}

static struct gpio_chip template_chip = {
	.label			= "wm8350",
	.owner			= THIS_MODULE,
	.direction_input	= wm8350_gpio_direction_in,
	.get			= wm8350_gpio_get,
	.direction_output	= wm8350_gpio_direction_out,
	.set			= wm8350_gpio_set,
	.to_irq			= wm8350_gpio_to_irq,
	.can_sleep		= true,
};

static int wm8350_gpio_probe(struct platform_device *pdev)
{
	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
	struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev);
	struct wm8350_gpio_data *wm8350_gpio;
	int ret;

	wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio),
				   GFP_KERNEL);
	if (wm8350_gpio == NULL)
		return -ENOMEM;

	wm8350_gpio->wm8350 = wm8350;
	wm8350_gpio->gpio_chip = template_chip;
	wm8350_gpio->gpio_chip.ngpio = 13;
	wm8350_gpio->gpio_chip.dev = &pdev->dev;
	if (pdata && pdata->gpio_base)
		wm8350_gpio->gpio_chip.base = pdata->gpio_base;
	else
		wm8350_gpio->gpio_chip.base = -1;

	ret = gpiochip_add(&wm8350_gpio->gpio_chip);
	if (ret < 0) {
		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
		return ret;
	}

	platform_set_drvdata(pdev, wm8350_gpio);

	return ret;
}

static int wm8350_gpio_remove(struct platform_device *pdev)
{
	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);

	gpiochip_remove(&wm8350_gpio->gpio_chip);
	return 0;
}

static struct platform_driver wm8350_gpio_driver = {
	.driver.name	= "wm8350-gpio",
	.driver.owner	= THIS_MODULE,
	.probe		= wm8350_gpio_probe,
	.remove		= wm8350_gpio_remove,
};

static int __init wm8350_gpio_init(void)
{
	return platform_driver_register(&wm8350_gpio_driver);
}
subsys_initcall(wm8350_gpio_init);

static void __exit wm8350_gpio_exit(void)
{
	platform_driver_unregister(&wm8350_gpio_driver);
}
module_exit(wm8350_gpio_exit);

MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:wm8350-gpio");

2、

/* linux/drivers/char/scx200_gpio.c

   National Semiconductor SCx200 GPIO driver.  Allows a user space
   process to play with the GPIO pins.

   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */

#include <linux/device.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <linux/types.h>
#include <linux/cdev.h>

#include <linux/scx200_gpio.h>
#include <linux/nsc_gpio.h>

#define DRVNAME "scx200_gpio"

static struct platform_device *pdev;

MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
MODULE_DESCRIPTION("NatSemi/AMD SCx200 GPIO Pin Driver");
MODULE_LICENSE("GPL");

static int major = 0;		/* default to dynamic major */
module_param(major, int, 0);
MODULE_PARM_DESC(major, "Major device number");

#define MAX_PINS 32		/* 64 later, when known ok */

struct nsc_gpio_ops scx200_gpio_ops = {
	.owner		= THIS_MODULE,
	.gpio_config	= scx200_gpio_configure,
	.gpio_dump	= nsc_gpio_dump,
	.gpio_get	= scx200_gpio_get,
	.gpio_set	= scx200_gpio_set,
	.gpio_change	= scx200_gpio_change,
	.gpio_current	= scx200_gpio_current
};
EXPORT_SYMBOL_GPL(scx200_gpio_ops);

static int scx200_gpio_open(struct inode *inode, struct file *file)
{
	unsigned m = iminor(inode);
	file->private_data = &scx200_gpio_ops;

	if (m >= MAX_PINS)
		return -EINVAL;
	return nonseekable_open(inode, file);
}

static int scx200_gpio_release(struct inode *inode, struct file *file)
{
	return 0;
}

static const struct file_operations scx200_gpio_fileops = {
	.owner   = THIS_MODULE,
	.write   = nsc_gpio_write,
	.read    = nsc_gpio_read,
	.open    = scx200_gpio_open,
	.release = scx200_gpio_release,
	.llseek  = no_llseek,
};

static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */

static int __init scx200_gpio_init(void)
{
	int rc;
	dev_t devid;

	if (!scx200_gpio_present()) {
		printk(KERN_ERR DRVNAME ": no SCx200 gpio present\n");
		return -ENODEV;
	}

	/* support dev_dbg() with pdev->dev */
	pdev = platform_device_alloc(DRVNAME, 0);
	if (!pdev)
		return -ENOMEM;

	rc = platform_device_add(pdev);
	if (rc)
		goto undo_malloc;

	/* nsc_gpio uses dev_dbg(), so needs this */
	scx200_gpio_ops.dev = &pdev->dev;

	if (major) {
		devid = MKDEV(major, 0);
		rc = register_chrdev_region(devid, MAX_PINS, "scx200_gpio");
	} else {
		rc = alloc_chrdev_region(&devid, 0, MAX_PINS, "scx200_gpio");
		major = MAJOR(devid);
	}
	if (rc < 0) {
		dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc);
		goto undo_platform_device_add;
	}

	cdev_init(&scx200_gpio_cdev, &scx200_gpio_fileops);
	cdev_add(&scx200_gpio_cdev, devid, MAX_PINS);

	return 0; /* succeed */

undo_platform_device_add:
	platform_device_del(pdev);
undo_malloc:
	platform_device_put(pdev);

	return rc;
}

static void __exit scx200_gpio_cleanup(void)
{
	cdev_del(&scx200_gpio_cdev);
	/* cdev_put(&scx200_gpio_cdev); */

	unregister_chrdev_region(MKDEV(major, 0), MAX_PINS);
	platform_device_unregister(pdev);
}

module_init(scx200_gpio_init);
module_exit(scx200_gpio_cleanup);

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值