gpt4 book ai didi

c - C中的内存分配从1到N

转载 作者:行者123 更新时间:2023-11-30 19:01:37 24 4
gpt4 key购买 nike

我有一个分配和初始化二维矩阵的函数。代码如下:

#include <stdio.h>
#include <stdlib.h>

#define SHIFT_IND 1

float **matrix(int mrl, int mrh, int mcl, int mch)
{

int k,
l,
mrow = mrh - mrl + 1,
mcol = mch - mcl + 1;
float **ma;

ma = (float **)malloc((size_t)((mrow + SHIFT_IND) * sizeof(float*)));
if (ma == NULL)
fprintf(stderr, "util.c: allocation failure 1 in function matrix()");
ma += SHIFT_IND;
ma -= mrl;

ma[mrl] = (float *) malloc((size_t)((mrow * mcol + SHIFT_IND) * sizeof(float)));
if (ma[mrl] == NULL)
fprintf(stderr, "util.c: allocation failure 2 in function matrix()");
ma[mrl] += SHIFT_IND;
ma[mrl] -= mcl;

for (k = mrl + 1; k <= mrh; k++)
ma[k] = ma[k - 1] + mcol;

for (k = mrl; k <= mrh; k++)
for (l = mcl; l <= mch; l++)
ma[k][l] = 0.0;

return ma;
}

我猜这段代码使矩阵的索引从 1N (N 是每个维度中元素的总数) ,不是传统的从0N-1,大小仍然是N*N。但我无法理解这段代码中的关键思想,尤其是 ma += SHIFT_IND; ma -= mrl;ma[mrl] += SHIFT_IND;
ma[mrl] -= mcl;
谁能给我画一张图来说明这段代码中内存是如何分配的吗?

最佳答案

I can't understand the key thought in this code, especially ma += SHIFT_IND; ma -= mrl; and ma[mrl] += SHIFT_IND; ma[mrl] -= mcl;

考虑分配后立即的 ma 值,并假设 mrl 为 3,mrh 为 6。代码将分配 ma 有足够的空间容纳 mrh - mrl + 1 + SHIFT_IND (== 5) 元素。我们可以通过表达式 ma[0]ma[1]、... ma[4] 等方式访问这些元素.

我们以表达式ma[3]为例。指针索引是表达指针算术和取消引用组合的另一种语法,在本例中为 *(ma + 3)

现在假设我们不是修改 ma,而是计算一个相同类型的新值,如 mb = ma + SHIFT_IND - mrl,在本例中计算结果如下到 mb = ma - 2。 (我们稍后会回到这一点。)进一步假设我们想要访问与 ma[3] 相同的元素,但通过 mb 代替。简单的代数就可以知道 ma + 3 == mb + 5,因此如果 ma[3]*(ma + 3) 的含义相同,以及ma + 3 == mb + 5,那么我们就可以访问与mb[5]相同的存储位置。按照同样的逻辑,我们还可以将 ma[1] 访问为 mb[3],将 ma[2] 访问为 mb[ 4]ma[4](最后分配的元素)为 mb[6]

这涵盖了从 mrlmrh 的范围,尽管它似乎浪费了一个元素,因为该范围内没有任何元素访问 ma[0].除了单元素丢失(这可能是故意的)之外,几乎可以肯定,这个想法是生成一个支持基于 mrl 的索引而不是基于 0 的索引的指针。由于 ma 是一个 float**,其所有元素本身都指向分配的空间,因此对元素的类似操作是类似的。

现在按照 promise 返回到前面的点:上述方案的问题在于计算 mb = ma + SHIFT_IND - mrl (以及 ma + = SHIFT_IND; ma -= mrl) 当 mrl 的值超过 1 或 mrl 的值足够负时,具有未定义的行为。在实践中,对于某些 C 实现,它可能仍然可以像上面描述的那样工作,但在其他一些实现中可能会失败,并且在某些实现中可能会出现不一致的行为。随着不同级别的编译器优化或代码修改,其行为发生变化的风险相对较高。这是不安全的。

老实说,这些索引游戏看起来像是 Fortran 习语的 C 改编,因为尽管 Fortran 默认为基于 1 的数组索引,但它允许使用任何所需的索引范围来声明数组,包括负界和下界更大比 1.C 没有。在 C 中,操纵访问指针的索引比操纵指针值本身以(也许)允许使用不同的索引进行访问要好得多。

关于c - C中的内存分配从1到N,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57513796/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com