转换旧的 C 代码
Converting old C code
我在项目源代码中有这个代码片段,我正在处理
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(((size_t *)(*p))++) = s;
}
gcc-4.7 不编译它。海合会 returns
lvalue required as increment operand
错误信息。我改成了
stp = ((size_t *)(*p));
*(stp ++) = s;
和
stp = ((size_t *)(*p));
*stp = *stp + 1;
*stp = s;
gcc 编译它们。但应用程序无法正常工作。
转换是真的吗?有什么转换工具吗?
*(((size_t *)(*p))++) = s;
Breakdown:
*(
(
(size_t *) (*p)
) ++
) = s
的意思是:将 *p
作为指向 size_t
的指针(之后我们称其为 ptr
),取消引用它(= 在地址 *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;
}
这个想法似乎是分配一定数量的内存(s
)和额外的数量来存储分配在与前导相同区域中的这个大小块,然后 return 指向存储大小后面的指针。
所以试试这个:
void func(void ** p, size_t s)
{
size_t * sp = malloc(s + sizeof s);
if (NULL != sp)
{
*sp = s;
++sp;
}
*p = sp;
}
顺便说一句,释放分配的内存并不简单。
一个典型的调用序列,也释放了这个函数 returns,然后看起来像这样:
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));
}
func2()
:添加变量可以提高可读性,恕我直言。 (然后内联将摆脱它)
- 第二个函数
func3()
演示了使用return值而不是通过引用传递一个(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;
}
尝试
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(*(size_t **)p)++ = s;
}
这是分配 s
字节的内存,加上足够的额外空间来容纳 s
,在 space 的开头存储 s
并修改 *p
指向之后。
更明智和更清晰(并避免转换!)将是:
void *func(size_t s)
{
size_t *p = malloc(s + sizeof(size_t));
if (p) *p++ = s;
return p;
}
但这需要更改调用此函数的代码以获取 return 值并将其存储在需要的任何位置,而不是将额外的指针作为参数传递:
some_ptr = func(needed_size);
而不是
func((void **)&some_ptr, needed_size);
也避免强制转换...
我在项目源代码中有这个代码片段,我正在处理
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(((size_t *)(*p))++) = s;
}
gcc-4.7 不编译它。海合会 returns
lvalue required as increment operand
错误信息。我改成了
stp = ((size_t *)(*p));
*(stp ++) = s;
和
stp = ((size_t *)(*p));
*stp = *stp + 1;
*stp = s;
gcc 编译它们。但应用程序无法正常工作。 转换是真的吗?有什么转换工具吗?
*(((size_t *)(*p))++) = s;
Breakdown:
*(
(
(size_t *) (*p)
) ++
) = s
的意思是:将 *p
作为指向 size_t
的指针(之后我们称其为 ptr
),取消引用它(= 在地址 *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;
}
这个想法似乎是分配一定数量的内存(s
)和额外的数量来存储分配在与前导相同区域中的这个大小块,然后 return 指向存储大小后面的指针。
所以试试这个:
void func(void ** p, size_t s)
{
size_t * sp = malloc(s + sizeof s);
if (NULL != sp)
{
*sp = s;
++sp;
}
*p = sp;
}
顺便说一句,释放分配的内存并不简单。
一个典型的调用序列,也释放了这个函数 returns,然后看起来像这样:
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));
}
func2()
:添加变量可以提高可读性,恕我直言。 (然后内联将摆脱它)- 第二个函数
func3()
演示了使用return值而不是通过引用传递一个(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;
}
尝试
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(*(size_t **)p)++ = s;
}
这是分配 s
字节的内存,加上足够的额外空间来容纳 s
,在 space 的开头存储 s
并修改 *p
指向之后。
更明智和更清晰(并避免转换!)将是:
void *func(size_t s)
{
size_t *p = malloc(s + sizeof(size_t));
if (p) *p++ = s;
return p;
}
但这需要更改调用此函数的代码以获取 return 值并将其存储在需要的任何位置,而不是将额外的指针作为参数传递:
some_ptr = func(needed_size);
而不是
func((void **)&some_ptr, needed_size);
也避免强制转换...