如果我只是放入第1行,那么“a”和“one.index1”都将指向类似的位置,这是我不想要的。我真正想要的是第2行和第3行。那么,它是唯一的方式,还是任何人都可以提供更好的方式?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *index1;
} data;
void doo(int *);
int main(int argc, char *argv[])
{
int *a = (int *) malloc(10*sizeof(int));
int i;
for(i=0; i<10; i++)
{
a[i] = 2*i;
}
doo(a);
data one;
//one.index1 = a; // Line 1
/*******************/
one.index1 = (int *) malloc(5*sizeof(int)); // Line 2
for(i=0; i<5; i++) one.index1[i] = a[i]; // Line 3
/*******************/
printf("%d\n", one.index1[4]);
free(a);
printf("%d\n", one.index1[4]);
free(one.index1);
return 0;
}
void doo(int *b)
{
b = (int *) realloc(b, 5*sizeof(int));
return;
}
提前致谢!
答案 0 :(得分:2)
doo将无法正常工作。它需要是:
void doo(int **b)
{
*b = (int *) realloc(*b, 5*sizeof(int));
return;
}
并通过
调用 doo(&a);
如果在malloc之后立即发生realloc,那么您的原始版本可能偶尔会意外地工作,因此有足够的空间来扩展内存块。但这不应该被依赖。
现在,要回答您的实际问题,由于我们正在处理简单的数据项(即整数),您可以使用memmove()
或memcpy()
来复制它们:(如果内存,memmove是安全的块重叠; memcpy不是,但这不是问题)
one.index1 = (int *) malloc(5*sizeof(int)); // Line 2
memcpy(one.index1, a, sizeof(int) * 5);
至于memmove / memcpy的效率,这几乎是一个未知领域。 memmove会对memcpy进行更多的范围检查,因此memcpy会慢一些。至于memcpy vs一个循环,很难说。 memcpy有更多的开销,但它被称为很多,所以编译器供应商有一个人花了很多时间确保它尽可能快。
但请注意,给定要复制的少量固定元素,最简单的方法是直接复制它们:
one.index1 = (int *) malloc(5*sizeof(int)); // Line 2
one.index1[0] = a[0];
one.index1[1] = a[1];
one.index1[2] = a[2];
one.index1[3] = a[3];
one.index1[4] = a[4];
答案 1 :(得分:1)
有些狡辩。
如果在调用函数之前定义函数(如果函数位于同一个源文件中),则生活会更容易;这样您就不必担心保持声明/定义同步。
请勿投射malloc()
的结果。从C89开始,你不需要这样做,如果忘记#include stdlib.h或者在范围内没有malloc()
的原型,那么这样做可能会抑制有用的诊断(尽管新的编译器正在捕获这个错误即使是演员,因为它经常发生如此血腥)。
在你要分配的东西上使用sizeof
运算符,而不是类型;再次,它使生活更简单,因为您不必保持声明和malloc()
调用同步。
如果希望函数修改指针参数,则必须传递指向该指针的指针:
void doo(int **p)
{
*p = realloc(*p, 5 * sizeof **p);
}
否则对形式参数p
的更改不会反映在实际参数中。
如果你抽象出你的记忆管理功能,生活也会更容易;你可以用一个函数调用替换第2行和第3行:
int *copy(int * const source, size_t len)
{
int *dest = malloc(len * sizeof *dest);
if (dest)
memcpy(dest, source, len * sizeof *source);
return dest;
}
你称之为
one.index1 = copy(a, len);
答案 2 :(得分:0)
您可以使用memmove。务必在开始时#include <string.h>
。
替换第2行和第2行3 by,
one.index1 = malloc( 5*sizeof(int) );
memmove(one.index1,a, 5*sizeof(int) );
例如,考虑一个&amp; c:
int *a= (int *) malloc(10*sizeof(int));
for(i=0; i<10; i++)
{
a[i] = 2*i;
}
int *c= (int *) malloc(10*sizeof(int));
memmove(c,a,10*sizeof(int));
现在既是&amp; c是单独的指针,指向“相同数据”&amp;可以单独释放。
a[0]=0 c[0]=0
a[1]=2 c[1]=2
a[2]=4 c[2]=4
a[3]=6 c[3]=6
a[4]=8 c[4]=8
a[5]=10 c[5]=10
a[6]=12 c[6]=12
a[7]=14 c[7]=14
a[8]=16 c[8]=16
a[9]=18 c[9]=18
这种新方法更有效吗?实际上,它是。比较程序运行所花费的时间:(我使用long long类型而不是int,以获得明显的时间差异)
旧方法:
$ time ./a.out
real 0m0.249s
user 0m0.178s
sys 0m0.070s
新方法:
$ time ./a.out
real 0m0.164s
user 0m0.095s
sys 0m0.068s
答案 3 :(得分:0)
您可以使用可能高度优化的memmove / memcpy函数:
const size_t size = 5*sizeof(int);
one.index = (int *) malloc(size);
memcpy(one.index, a, size);
当然,你可以把它包装成一个函数:
int *getCopy(const int *source, size_t count)
{
int *result = (int *)malloc(count * sizeof(int));
if (!result)
return NULL;
memcpy(result, source, count * sizeof(int));
return result;
}
// Usage
one.index = getCopy(a, 5);
答案 4 :(得分:0)
这取决于你想要避免的关于第2行第3行的具体内容。如果你想避免循环,请使用memcpy,尽管大多数编译器应该使用等同于memcpy调用的代码替换你的循环。如果你想要一个单行操作,你可以编写一个静态函数,它接受one.index1的地址,数组a的大小和a参数。
int * f (int **int_pp, size_t len, int const *a) {
*int_pp = (int *) malloc (len * sizeof (int));
if ( *int_pp != NULL ) {
memcpy (*int_pp, a, len);
}
return *int_pp;
}
不要忘记检查malloc是否返回NULL!
如果你想避免对malloc的调用,我认为唯一的选择是将你手动管理的一块内存放在一边。但是,尝试自己管理内存几乎是不值得的。