转换旧的C代码

时间:2015-06-10 15:49:02

标签: c gcc porting

我在项目源代码中有这个代码片段,我在

上工作
void func(void **p,size_t s)
{
    *p = malloc(s+sizeof(size_t));
    *(((size_t *)(*p))++) = s;
}

和gcc-4.7不编译它。 gcc返回

lvalue required as increment operand 

错误消息。我把它改成了

stp = ((size_t *)(*p));
*(stp ++) = s;

stp = ((size_t *)(*p));
*stp = *stp + 1;
*stp = s;

gcc编译它们。但是应用程序无法正常工作。 转换是真的吗?是否有任何转换工具?

4 个答案:

答案 0 :(得分:1)

这个想法似乎是分配一定数量的内存(s一个额外的数量来存储在与前导块相同的区域中分配的这个大小,然后返回一个指向存储大小后面的指针。

所以试试这个:

void func(void ** p, size_t s)
{
  size_t * sp = malloc(s + sizeof s);
  if (NULL != sp)
  {
    *sp = s;
    ++sp;
  }

  *p = sp;
}

顺便说一下,释放分配的内存并不是直截了当的。

一个典型的调用序列,也释放了这个函数返回的内容,如下所示:

void * pv = NULL;
func(&pv, 42);
if (NULL != pv)
{
  /* Use 42 bytes of memory pointed to by pv here. */

  free(((char *) pv) - sizeof (size_t));
}

答案 1 :(得分:0)

*(((size_t *)(*p))++) = s;

Breakdown:
*(
  (
    (size_t *) (*p)
  ) ++
) = s

意味着:将*p作为指向size_t的指针(让我们称之为ptr),取消引用它(=取size_t类型的值在地址*p),将该值分配给s并最终增加ptr(也就是说*p增加sizeof(size_t)中的地址。

您可以将其翻译为:

size_t *ptr = (size_t*)(*p); //second pair of paren is optionnal
s = *ptr;
ptr = ptr + 1; //Warning: This will only modify the variable ptr and not
               //the data at its original place *p, if the remainder of
               //the program is based on that (which I highly suspect)
               //you should do instead :

(size_t*)*p = (size_t*)(*p) + 1; //This also ensures "+1" is treated as
                                 //"add the sizeof(size_t)" because *p
                                 //points to a size_t typed variable

你也可以重新输入一个变量,让它指向与p相同的位置,并使用强制转换完成:

void func(void **p,size_t s)
{
  size_t **ptr = p;
  *ptr = malloc(s+sizeof(size_t));

  if (*ptr == NULL) etc...

  *((*ptr)++) = s;
}

答案 2 :(得分:0)

  • func2():添加变量可以提高可读性,恕我直言。 (并且内联将在之后摆脱它)
  • 第二个函数func3()演示了使用返回值而不是通过引用传递( opaque )指针可以避免复杂性和强制转换
#include <stdio.h>
#include <stdlib.h>

void func2(void **p,size_t s)
{
    size_t **pp;
    pp = (size_t **) p; // only one cast
    *pp = malloc(s+sizeof(size_t));
    if (!*pp) return;
                          fprintf(stderr,"[mallocd %p]", *pp);
    *pp[0] = s;
    *pp += 1;
}

void *func3(size_t s)
{
    size_t *p;
    p = malloc(s+sizeof *p);
    if (!p) return NULL;
                          fprintf(stderr,"[mallocd %p]", p);
    p[0] = s;
    return p+1;
}

int main(void)
{
char *p = NULL , *p2 = NULL;

func2( (void**) &p, 666);       // yet another cast
fprintf(stderr,"returned p := %p\n", p);

p2 = func3( 666); // No cast!!!
fprintf(stderr,"returned p2 := %p\n", p2);

return 0;
}

答案 3 :(得分:0)

void func(void **p,size_t s)
{
    *p = malloc(s+sizeof(size_t));
    *(*(size_t **)p)++ = s;
}

这是分配s字节的内存,加上足够的额外内容来保存s,将s存储在该空间的开头,并将*p修改为在此之后指向

更明智和更清晰(并避免演员阵容!)将是:

void *func(size_t s)
{
    size_t *p = malloc(s + sizeof(size_t));
    if (p) *p++ = s;
    return p;
}

但是这需要更改调用此函数的代码来获取返回值并将其存储在任何需要的位置,而不是将额外的指针作为参数传递:

some_ptr = func(needed_size);

而不是

func((void **)&some_ptr, needed_size);

也避免演员......