首页 > 其他分享 >C语言中两个不同类型的结构体相互幅值

C语言中两个不同类型的结构体相互幅值

时间:2025-01-09 09:30:07浏览次数:3  
标签:arrB C语言 幅值 数组 相互 sB 赋值 memcpy 结构

在 C 语言中,如果两个结构体的定义(字段名称、数量、顺序、类型)不一样,就不能直接使用 = 运算符进行整体赋值,需要逐个字段进行赋值或者通过其它手段进行“转换”。


1. 字段一一对应赋值

1.1 手动逐个赋值

假设有如下两个结构体:

typedef struct 
{
    int  id;
    char name[20];
    int  age;
} StuA;

typedef struct
{
    int  stuId;
    char stuName[20];
    int  birthYear;
} StuB;

如果想把 StuA 类型变量中的信息赋值给 StuB 类型变量,只能手工逐个字段对照相应含义进行赋值。例如:

void convertAtoB(const StuA *src, StuB *dst)
{
    // 1) 把 src->id 赋给 dst->stuId
    dst->stuId = src->id;
    
    // 2) 把 src->name 字符数组复制到 dst->stuName
    //    可以用 strcpy,memcpy 等,但要注意数组长度、是否有字符串结束符 '\0' 等
    strcpy(dst->stuName, src->name);
    
    // 3) 根据需求,假设 age 和 birthYear 之间存在一定关系 
    //    可能需要额外处理,如:birthYear = 当前年份 - age
    //    这里仅做简单举例
    dst->birthYear = 2025 - src->age;
}

然后在调用处:

StuA a = {1001, "Alice", 20};
StuB b;

convertAtoB(&a, &b);

// 测试打印
printf("b.stuId = %d\n", b.stuId);
printf("b.stuName = %s\n", b.stuName);
printf("b.birthYear = %d\n", b.birthYear);

特点

  • 完全可控,每个字段怎么赋值都可以自己定规则(例如做一些计算、类型转换等)。
  • 写法简单明了,但需要维护多行代码,且结构体字段越多,越繁琐。

1.2 结合结构体内不同字段做适配

有时字段名称或类型并不完全对应,需要在转换时做一些逻辑处理。上面已经演示了把 age 转成 birthYear。这种场景是没有直接通用的“整体复制”方法的,只能手写适配逻辑。


2. 如果结构体布局“完全相同”但名字不同

如果两个结构体字段布局完全一致(包括类型、数量、对齐方式等),只是结构体名字不同,在某些情况下,可以通过 memcpy 来“复制”内存内容。

举个例子:

typedef struct
{
    int  x;
    float y;
} MyStructA;

typedef struct
{
    int  x;
    float y;
} MyStructB;

此时它们的内存布局其实是一模一样的,仅名字不一样。可以用:

#include <string.h>

MyStructA a = {1, 2.5f};
MyStructB b;

memcpy(&b, &a, sizeof(b)); // 或 sizeof(a) 因为大小一样

然后 b.xb.y 分别与 a.xa.y 值相同。但需要特别注意:如果两个结构体字段类型、对齐方式不一致,或者我们需要对字段进行特殊处理,这种做法就会出问题。


3. 不同结构体之间数组相互幅值

在 C 语言中,如果只是想将两个结构体中的数组相互赋值(拷贝数据),可以使用 `memcpy` 或逐元素拷贝。下面介绍两种常见方式。


假设结构体定义

举例说明,假设我们有如下两个结构体,都含有一个长度相同的数组:

#include <stdint.h>

typedef struct
{
    uint8_t arrA[10];
    // ... 其他字段
} StructA;

typedef struct
{
    uint8_t arrB[10];
    // ... 其他字段
} StructB;

并且有对应的结构体变量:

StructA sA;
StructB sB;

现在您只想把 sA 中的数组 arrA 拷贝到 sB 中的数组 arrB


方法一:使用 memcpy 拷贝数组

如果您确定两个数组长度相同,且确实要把所有字节都复制过去,那么最简洁的做法是:

#include <string.h>  // memcpy 所在头文件

memcpy(sB.arrB, sA.arrA, sizeof(sB.arrB));
  • sB.arrB: 目标数组的首地址

  • sA.arrA: 源数组的首地址

  • sizeof(sB.arrB): 要复制的数据大小(单位:字节)

这样就完成了从 sA.arrAsB.arrB 的数据拷贝。

关键注意事项

  1. 数组长度需相同
    如果两边数组长度不一致,建议使用 sizeof(最短的数组) 或者确保不会越界访问。

  2. memcpy 与字符串
    如果数组保存的是字符串,需要您手动保证目标数组中是否需要末尾 '\0',或者使用 strcpy(适合以 '\0' 结尾的 C 字符串)。但如果只是普通的数据(字节流),memcpy 就更合适。

  3. memcpy 只做纯字节复制
    它不会考虑任何类型转换或深拷贝结构,只是一份内存到另一份内存的原样复制。


方法二:逐元素拷贝(for 循环)

如果想在复制过程中做一些额外操作、检查或转换,或者两边数组大小并不一样,我们可以使用 for 循环逐元素拷贝。例如:

void copyArray(const StructA *source, StructB *dest, uint8_t length)
{
    // 这里 length 可以是两个数组中的最小长度,以避免越界
    for (uint8_t i = 0; i < length; i++)
    {
        dest->arrB[i] = source->arrA[i];
    }
}

然后调用时:

copyArray(&sA, &sB, 10); // 假设要拷贝 10 个字节

关键注意事项

  1. 可控性
    在循环中我们可以加判定逻辑、打印、或做任何数据变换,而不必再写额外的循环代码。

  2. 不用担心结构体中其它字段
    只要针对目标数组和源数组进行处理就行,不会影响到结构体的其它部分。


总结

  1. 结构体字段不一样时,必须逐个字段赋值或使用适配函数,把源结构体的各字段对应到目标结构体的字段。
  2. 如果内存布局一模一样,只是名字不同,可以通过 memcpy 整体复制,但是要非常确定二者的字段定义、对齐方式、大小都相同。
  3. 如果两个结构体中数组大小完全相同,且只想做简单的字节复制,推荐使用 `memcpy`
  4. 如果需要额外逻辑处理,或者数组大小不一致,或想逐字节检查,可以使用 for 循环 逐元素赋值。

在大多数场景下,手动一一对应字段仍是最常见且安全的做法。

标签:arrB,C语言,幅值,数组,相互,sB,赋值,memcpy,结构
From: https://blog.csdn.net/FCZlll/article/details/145022556

相关文章

  • 【C语言】打印菱形
    目录前言一、题目介绍1.1问题描述1.2输入描述1.3 输出描述1.4示例 二、基本思路三、代码实现3.1基本框架3.2pirnt函数的实现四、效果展示 五、完整代码前言在牛客网刷题时碰到的一道题,基础语法篇中的BC8牛牛的字符菱形,我相信在其它地方也有类似的......
  • C语言编程常见错误与防范策略(大纲)
            引言 C语言自1972年诞生以来,因其高效、灵活的特性,在系统编程、嵌入式开发等领域占据了不可替代的地位。然而,C语言的这些特性也是一把双刃剑,容易导致编程错误。本文将总结C语言编程中常见的错误类型,并提出相应的防范策略。本文为大纲,下一章将针对大纲进行举例......
  • C语言程序设计-学生基本信息管理系统
    学生基本信息管理系统题目(1)任务描述为某学校学生管理部门日常管理学生基本信息,设计一个信息管理系统。某学校学生管理部门在新生入学时,会登记每个学生的个人基本信息,以便今后提供给教务处、学生所在系部、毕业工作指导委员会等部门使用。(2)功能要求①根据自己初次入学时填写......
  • C语言数据结构与算法(二叉树)
    1.二叉树的概念及结构1.1概念一棵二叉树是结点的一个有限集合,该集合:1.或者为空2.由一个根节点加上两棵别称为左子树和右子树的二叉树组成特性:1.二叉树不存在度大于2的结点2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树1.2特殊的二叉树满二叉树:每......
  • C语言中指针类型强转之后解引用出现问题
    函数中传入的参数是指针类型但是该指针类型是类型强转之后传入函数在函数调用过程中解引用指针的时候出现了keil-hardfault。首先查看MSP的值然后在内存中输入msp的值在反汇编窗口中输入地址找到出错的函数发现故障原因是在解引用指针时,由于指针类型出现强转,需要对......
  • 【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
    目录......
  • C语言实现通讯录(动态的版本)
    通讯录的实现框架动态的版本通讯录默认能存放3个人的信息如果空间不够了,就增加空间,每次增加2个人的空间实现一个通讯录:人的信息:名字+年龄+性别+电话+地址1.增加联系人2.删除指定联系人3.查找联系人4.修改联系人5.显示联系人6.排序测试功能test.c......
  • C语言实现对函数求积分(终端输入函数型)
    本文只提供源码,不会进行代码讲解,如需部分讲解,请前往我的另一篇文章C语言对各类复杂函数精确求导(在终端解析字符串并求导)_c语言导数函数-CSDN博客支持+-*/exp()sin()cos()tan()cot()^arc函数 log(底数,真数)输入格式为:JF<函数>dx#include<stdio.h>#include<......
  • C语言指针数组
    1. 指针数组的定义指针数组是数组,其元素为指针。定义格式为 数据类型*数组名[数组大小] 。例如,定义一个能存放5个指向 int 类型数据的指针数组: cint*ptrArray[5];  2. 初始化-方式一:直接初始化 cintnum1=10,num2=20;int*ptrArray[]={&num......
  • C语言的学习路线
    C语言的学习路线C语言是一种广泛使用的编程语言,它以其高效、灵活和接近底层的特性被广泛应用于系统编程、嵌入式系统、操作系统和众多应用程序开发中。对于初学者来说,学习C语言不仅是了解计算机编程的一个良好起点,同时也为后续学习其他编程语言打下坚实的基础。本文将详细......