gpt4 book ai didi

c - 如何避免涉及 ptr 到 ptr 到 ptr 的不必要的转换和无关变量

转载 作者:行者123 更新时间:2023-11-30 20:13:31 27 4
gpt4 key购买 nike

我有以下代码,完全可以 100% 正常运行,没有错误、编译或运行时。但这太难看了,因为当我确定有办法不需要其中任何一个时,我必须强制转换并使用一个无关的变量。

structMSGB ***init_bstack(int Blk_Size,int Blks_N)
{
structMSGB **Mp=calloc(Blk_Size,Blks_N);
void *M=(void*)Mp+sizeof(structMSGB*)+sizeof(structMSGB*)*Blks_N;

structMSGB ***startStack=(structMSGB***)Mp++;

for(int i=0;i<Blks_N;i++)
{
*Mp=M+(Blk_Size-sizeof(structMSGB*))*i-(i==1)*sizeof(structMSGB*);
(*Mp)->blk_size=Blk_Size-sizeof(structMSGB)-sizeof(structMSGB*)-(i==0)*sizeof(structMSGB*);
Mp++;
}

*startStack=(structMSGB **)Mp;
return startStack;
}

具体来说,是 startStack 变量让我生气。我觉得应该有一种完全不需要它的方法。返回值是一个ptr to a ptr to a struct的地址,即需要返回一个ptr to a ptr to a ptr to a struct。

返回的结果是一个大小为Blk_Size字节的内存块的起始地址,按顺序由以下部分组成:

**ptr 变量

Blk_N 长度的指针表

大小为 Blk_Size - sizeof(ptr) 的连续 block ,除了第一个 block 的 sizeof(ptr) 更小。

这样做是为了确保使用整个内存分配,不多也不少。

最佳答案

您的代码在对 void * 类型的表达式执行算术运算时会调用未定义的行为。某些编译器会将其视为 void *char *,如果您的代码确实有效,那么这就是正在发生的情况,但它仍然是错误的。并且可能不需要启动。

请允许我向您介绍指针算术。给定一个 some_type * 类型的指针 p 和一个整数值 x,表达式 p + x 等价于(some_type *) (((char *) p) + (x * sizeof(some_type))。绝非巧合,这也相当于 &p[x]。也就是说,指针算术是根据所指向对象的大小来定义的。

您提供的代码执行了大量具有显式对象大小的转换和算术,这些可以通过依赖普通指针算术来消除。例如,这个...

void *M = (void*) Mp + sizeof(structMSGB*) + sizeof(structMSGB*) * Blks_N;

...写得更好

structMSGB **M = Mp + 1 + Blks_N;

类似的情况也适用于代码中的其他地方。

更一般地说,除了内存分配之外,好的代码很少需要 sizeof,并且需要很少的强制转换。任何时候你发现自己在写类型转换,你都应该问自己为什么,并确保你有一个好的答案。

更新:

至于摆脱变量startStack,看起来您可以以一些额外的算术为代价来做到这一点。您将其初始化为变量Mp 的原始值。然后,您将 Mp 增加总共 Blks_N + 1 次。在唯一使用 startStack 的地方,它的值等于 Mp - (Blks_N + 1)。您可以使用该表达式而不是变量。不过,我当然不会做出这样的改变。

关于c - 如何避免涉及 ptr 到 ptr 到 ptr 的不必要的转换和无关变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30004707/

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