memmove移动二维double数组仅迁移半数数据的原因咨询
二维double数组内存移动的字节数问题解析
嘿,这个问题的核心在于你没搞清楚C语言里二维数组的内存存储布局,以及memmove这类内存操作函数是如何处理连续内存块的。我给你拆解一下关键逻辑:
1. 二维数组的内存是「行优先连续存储」
你定义的double Weights[wt][2],在内存里并不是像表格那样按列排列的,而是把每一行的所有元素连续存放,再接下一行的元素。比如wt=3时,内存顺序是:Weights[0][0] → Weights[0][1] → Weights[1][0] → Weights[1][1] → Weights[2][0] → Weights[2][1]
也就是说,第一列的元素(Weights[i][0])之间并不是连续的,每两个第一列元素中间隔了一个第二列的元素(Weights[i][1])。
2. 为什么wt * sizeof(double)只能迁移半数数据?
假设你的需求是把第一列的所有wt个元素复制到第二列对应的位置,那用memmove(Weights[0]+1, Weights[0], wt * sizeof(double))就错了:
- 这个调用会从
Weights[0][0]开始,拷贝连续的wt个double(也就是wt*8字节,假设double为8字节)。 - 但这些连续的
double里,一半是第一列元素,一半是第二列元素(比如wt=169时,前84行的两个元素+第85行的第一个元素,总共169个)。 - 拷贝到
Weights[0][1]开始的位置后,只能覆盖第二列的前84个元素,剩下的第二列元素根本没被触及,所以你看到“仅能迁移约半数数组数据”。
3. 为什么加*2就能实现?
当你把字节数改成wt * 2 * sizeof(double)时,其实是拷贝了整个二维数组的所有元素(总共wt*2个double),从Weights[0][0]到Weights[wt-1][1]全部拷贝到Weights[0][1]开始的位置。
- 虽然这会超出原数组的范围(属于未定义行为),但恰好让你看到
Weights[0][0]的数据出现在Weights[0][1]里,同时其他行的第一列数据也被覆盖到了第二列位置(连续拷贝把所有元素整体移了一位)。
正确的实现方式
如果你只是想把每一行的第一个元素赋值给第二个元素,根本不需要用memmove,直接用循环更安全清晰:
for (int i = 0; i < wt; i++) { Weights[i][1] = Weights[i][0]; }
如果确实需要用内存操作函数,得针对列元素的非连续性处理,比如逐行拷贝单个元素:
for (int i = 0; i < wt; i++) { memmove(&Weights[i][1], &Weights[i][0], sizeof(double)); }
内容的提问来源于stack exchange,提问作者Brian Lafferry
相关产品推荐
相关产品推荐

