1.2 struct 结构体 深入

本文探讨了结构体在程序设计中的高级应用,包括如何将结构体作为结构体成员使用,结构指针作为结构成员的应用场景,以及位字段的概念与用途。通过具体示例,读者可以了解到这些特性在内存管理和数据组织方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4、深入结构体

将结构体作为结构体成员
1:
struct Date
{
	int day;
	int month;
	int year;
};
struct Person
{
	struct Date birth;
	int age;
	int height;
	char name[20];
	char mother[20];
}p1,p2;

访问结构体中的结构体成员p1.birth.day = 14;p1.birth.month = 5;p1.birth.1992;2:
struct Person
{
	struct Date
	{
		int day;
		int month;
		int year;
	}birth;
	int age;
	int height;
	char name[20];
	char mother[20];
}p1,p2;

访问方法同上;
注: struct Date my_date; //错误
错误信息说明 Date 结构未定义,如果要使用Date 必须在person 结构体外部定义。

将结构指针用作结构成员
struct perosn
{
	int age;
	int height;
	char name[20];
	char father[20];
	char mother[20];
	struct person *next;
};

这种类型的结构体主要用在链表上,还有双向链表等,在后面介绍。


结构中的位字段
位字段: 允许定义变量来表示一个整数中的一个活多个位。
注意: 位字段常用在必须节省内存的情况下, 与标准类型的变量相比,位字段会明显降低程序执行速度。
struct {
	unsigned int flag1 :1;
	unsigned int flag2 :1;
	unsigned int flag3 :2;
	unsigned int flag4 :3;
}indicators;


以字长为单位分配内存。
<think>我们正在讨论OpenSSL中CMS(Cryptographic Message Syntax)结构体的自定义问题。用户想知道是否允许修改CMS结构体的定义。 首先,CMS是用于数字签名、加密、摘要等操作的PKI数据结构标准(RFC 5652)。在OpenSSL中,CMS相关的功能由`crypto/cms`目录下的代码实现,其结构体定义主要在`cms_local.h`等头文件中。 OpenSSL中的CMS结构体通常是基于ASN.1(Abstract Syntax Notation One)定义的,并通过OpenSSL的ASN.1模块进行编解码。这些结构体在OpenSSL中是固定的,因为它们是按照标准定义的。但是,OpenSSL提供了一些扩展机制: 1. **自定义属性**:CMS支持添加自定义属性(例如,在签名者信息中),可以通过`CMS_signed_add1_attr`等函数添加。 2. **自定义内容类型**:虽然CMS标准定义了一些内容类型(如数据、签名数据、加密数据等),但OpenSSL允许处理自定义的内容类型,通过`CMS_ContentInfo`结构中的`contentType`字段指定一个OID(对象标识符),并实现相应的处理函数。 3. **自定义证书选择回调**:在处理CMS消息时,可以设置回调函数来自定义证书的选择过程。 但是,直接修改OpenSSL源代码中CMS结构体的定义(如修改`struct CMS_SignerInfo_st`)是不被推荐的,因为: - 这会导致与标准的不兼容,可能无法与其他实现互操作。 - 在升级OpenSSL版本时,自定义修改可能会带来冲突和维护困难。 因此,OpenSSL通常不允许在运行时修改CMS结构体的内存布局。但是,可以通过以下方式间接实现自定义: - **使用OpenSSL的ASN.1扩展机制**:OpenSSL允许注册自定义的ASN.1模板,从而可以解析和生成非标准的结构。这需要深入了解OpenSSL的ASN.1模块。 - **在CMS消息中添加自定义字段**:通过使用自定义属性(OID),可以将额外信息添加到CMS消息中,而不破坏标准结构。 例如,添加一个自定义属性到签名者信息: ```c CMS_SignerInfo *si = ...; // 获取签名者信息 ASN1_OBJECT *obj = OBJ_nid2obj(NID_custom_oid); // 自定义OID ASN1_TYPE *type = ASN1_TYPE_new(); type->type = V_ASN1_UTF8STRING; type->value.utf8string = ASN1_UTF8STRING_new(); ASN1_UTF8STRING_set(type->value.utf8string, "custom value", -1); if (CMS_signed_add1_attr_by_OBJ(si, obj, type) != 1) { // 错误处理 } ``` 总结:虽然不能直接修改CMS结构体的定义(因为它们是按照标准ASN.1模块生成的),但可以通过添加自定义属性或使用自定义内容类型来扩展CMS消息。如果必须添加全新的结构,则需要通过OpenSSL的ASN.1扩展机制注册新的ASN.1模板,但这需要深入理解OpenSSL的ASN.1实现。 §§相关问题§§ 1. 如何在OpenSSL中添加自定义的CMS属性? 2. OpenSSL中CMS结构体的ASN.1定义在哪里可以找到? 3. 如何解析包含自定义属性的CMS消息? 4. 使用自定义属性是否会影响CMS消息的互操作性?</think>### OpenSSL CMS 结构体定义的自定义能力 在 OpenSSL 中,**CMS(Cryptographic Message Syntax)结构体的核心定义通常是固定的**,因为它们基于 PKCS#7 和 RFC 5652 标准规范[^1]。但 OpenSSL 仍提供以下扩展机制实现有限的自定义: #### 允许的扩展方式 1. **自定义属性(Attributes)** 可在 `CMS_SignerInfo` 中添加自定义属性: ```c CMS_SignerInfo *si = ...; ASN1_OBJECT *obj = OBJ_create("1.2.3.4.5", "customAttr", "Custom Attribute"); ASN1_STRING *data = ASN1_STRING_new(); ASN1_STRING_set(data, "value", 5); CMS_signed_add1_attr_by_OBJ(si, obj, V_ASN1_OCTET_STRING, data, -1); ``` 2. **自定义内容类型** 通过注册新的 ASN.1 内容处理器: ```c ASN1_ITEM *CUSTOM_CONTENT_it = &MY_CUSTOM_ITEM; CMS_ContentInfo_set0_type(ci, OBJ_nid2obj(NID_custom_content), CUSTOM_CONTENT_it); ``` 3. **回调函数扩展** 在签名/验证流程中插入钩子函数: ```c CMS_SignerInfo_sign(si); CMS_SignerInfo_set1_signer_cert(si, cert, custom_signing_callback); ``` #### 禁止的修改 - ❌ 直接修改 `CMS_ContentInfo`、`CMS_SignerInfo` 等核心结构体的内存布局 - ❌ 更改标准字段(如 `version`、`digestAlgorithm`)的 ASN.1 编码规则 - ❌ 移除必需字段(会导致解析失败) #### 注意事项 1. **互操作性风险** 自定义属性可能被其他标准库忽略或拒绝[^2]。 2. **版本兼容性** OpenSSL 3.0 的 Provider 机制可能提供新扩展方式。 3. **替代方案建议** 如需深度定制,可考虑: - 使用 `BIO` 流封装自定义数据 - 在 CMS 外部封装元数据 - 改用更灵活的 CMS 替代方案(如 JOSE) > ⚠️ 直接修改结构体定义需要重新编译 OpenSSL,且会破坏标准兼容性,通常不推荐。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值