You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用memcpy复制结构体位域数据出错致程序崩溃,如何解决?

问题:使用memcpy复制结构体位域导致程序崩溃

我尝试使用memcpy将自定义结构体中某个unsigned int位域的部分数据复制到另一个unsigned int位域中,但程序仅打印第一条printf语句后就崩溃,返回错误码:Process returned -1073741819 (0xC0000005)。我是否错误使用了memcpy?

代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
    struct time
    {
        unsigned int hours:5;
        unsigned int minutes:6;
        unsigned int seconds:6;
    };

    struct time t = {0x10,0b101011,45};

    printf("The time is : %d:%d:%d\n", t.hours, t.minutes, t.seconds);

    memcpy(t.minutes, t.seconds, 2);

    printf("The time is : %d:%d:%d\n", t.hours, t.minutes, t.seconds);

    return 0;
}

我已经试过直接赋值t.minutes = t.seconds,这会复制整个数值,但我只想复制其中的一部分。


解答

首先,你确实错误使用了memcpy,这也是程序崩溃的直接原因:

  • memcpy的前两个参数必须是指针(内存地址),但你直接传入了位域的数值。t.minutes和t.seconds是位域成员,访问它们时会返回对应的整数值,而非内存地址。把数值当作指针传入memcpy,会导致程序访问非法内存地址,触发0xC0000005(访问违规)错误。

其次,位域本身不适合用memcpy操作:

  • 位域是编译器实现的内存打包方式,位域成员的具体内存布局(比如落在哪个字节的哪些位)属于未定义行为,不同编译器甚至同一编译器的不同编译选项都可能有差异。你无法直接通过内存地址精准定位到位域的某几个位,自然不能用memcpy复制部分位。

如果只想复制seconds中的部分位到minutes,用位运算是正确的解决方案,举几个常见场景的示例:

示例1:复制seconds的低4位到minutes的低4位,保留minutes的高2位

// 先清除minutes的低4位,再将seconds的低4位写入
t.minutes = (t.minutes & 0b110000) | (t.seconds & 0b001111);

示例2:复制seconds的第3到第5位(从0开始计数)到minutes的第0到第2位

unsigned int target_bits = (t.seconds >> 3) & 0b111; // 取出目标位并移到低3位
t.minutes = (t.minutes & ~0b111) | target_bits; // 清除minutes对应位后写入

示例3:将seconds的全部6位覆盖到minutes

t.minutes = t.seconds & 0b111111; // 等价于直接赋值t.minutes = t.seconds,位域会自动截断超出位数的部分

总结:操作位域的部分数据,正确方式是使用位掩码、移位等位运算,而非memcpy。


内容的提问来源于stack exchange,提问作者gloriousnoob100

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 11:01:01