ansi-c,更好的将数组元素复制到另一个数组?

时间:2010-09-24 16:14:20

标签: c

无论如何,我在第2行和第3行做了什么,smth类似于第1行?

如果我只是放入第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;
}

提前致谢!

5 个答案:

答案 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的调用,我认为唯一的选择是将你手动管理的一块内存放在一边。但是,尝试自己管理内存几乎是不值得的。