简体   繁体   English

转换旧的C代码

[英]Converting old C code

I have this code snippet in project source code which I work on 我在工作的项目源代码中有此代码段

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

and gcc-4.7 does not compile it. 而gcc-4.7不会编译它。 gcc returns gcc返回

lvalue required as increment operand 

error message. 错误信息。 I changed it into 我把它改成了

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

and

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

gcc compiles both of them. gcc编译它们两者。 But application does not work expected. 但是应用程序无法正常工作。 Is conversion true? 转换是真的吗? And is there any tool for conversion? 有转换工具吗?

The idea seems to be to allocate a certain amount of memory ( s ) and an additional amount to store this size allocated in the same area as a leading block and then return a pointer to just behind the stored size. 这个想法似乎是分配一定量的存储器( s附加量来存储该尺寸在同一区域分配作为一个领先的块,然后返回一个指向后面所存储的大小。

So try this: 所以试试这个:

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

  *p = sp;
}

Btw, freeing the allocated memory, is not straight forward. 顺便说一句,释放分配的内存,不是直接的。

A typicall sequence of calls, also freeing what this function returns, would look like this then: 一个典型的调用序列,也释放了该函数返回的内容,则如下所示:

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));
}
*(((size_t *)(*p))++) = s;

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

Means : Take *p as a pointer to size_t (let's call that ptr for after), dereference it (= take the size_t typed value at the address *p ), assign that value to s and finally increment ptr (which is to say increment the address in *p by the sizeof(size_t) . 意思是:以*p作为指向size_t的指针(在之后调用该ptr ),取消引用(=在地址*p处获取size_t输入的值),将该值分配给s,最后递增ptr (也就是说,递增*p的地址乘以sizeof(size_t)

You can translate that to: 您可以将其转换为:

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

You could also retype a variable and have it point at the same location as p and be done with the casts: 您还可以重新输入变量,并将其指向与p相同的位置,并通过强制转换进行操作:

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

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

  *((*ptr)++) = s;
}
  • func2() : Adding a variable can increase readability, IMHO. func2() :添加变量可以提高可读性,恕我直言。 (and inlining will get rid of it, afterwards) (然后,内联将摆脱它)
  • The second function func3() demonstrates that using the return value instead of passing a ( opaque ) pointer by reference can avoid complexity and casts 第二个函数func3()演示了使用返回值而不是通过引用传递( 不透明的 )指针可以避免复杂性和强制转换

#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;
}

try 尝试

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

This is allocating s bytes of memory, plus enough extra to hold s , storing s at the start of that space and modifying *p to point just after that. 这将分配s个字节的内存,外加足够多的空间来容纳s ,在该空间的开始处存储s ,并修改*p使其紧随其后。

More sensible and clearer (and avoiding casts!) would be: 更明智,更清晰(并避免强制转换!)将是:

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

but that requires changing the code that calls this function to take the return value and store it wherever desired, rather than passing an extra pointer as an argument: 但这需要更改调用此函数的代码以获取返回值并将其存储在所需的位置,而不是传递额外的指针作为参数:

some_ptr = func(needed_size);

rather than 而不是

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

also avoiding casts... 还避免演员表...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM