简体   繁体   English

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

[英]ansi-c, better copy array elements to another array?

is there anyway to do what I do in Lines 2 and 3, with smth similar to Line 1? 无论如何,我在第2和第3行中所做的工作与第1行类似吗?

If I just put Line 1, then both "a" and "one.index1" will be pointing to similar location, which I do not want. 如果我只放置第1行,那么“ a”和“ one.index1”都将指向相似的位置,这是我不希望的。 What I really want is done by Lines 2 and 3. So, is it the only way, or can anyone give better way? 我真正想要的是由第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;
}

Thanks in advance! 提前致谢!

doo will not work as it is. 斗不会按原样工作。 It would need to be: 它必须是:

void doo(int **b) 
{ 
 *b = (int *) realloc(*b, 5*sizeof(int)); 
 return; 
} 

and called by 并由

 doo(&a);

Your original version may occasionally accidently work, if the realloc occurs immedaitely after the malloc, so there is space to expand the memory block in place. 如果重新分配在malloc之后立即发生,则原始版本有时可能会偶然工作,因此有足够的空间来扩展内存块。 But that should not be counted on. 但这不应该指望。

Now, to answer your actual question, Since we are dealing with simple data items (ie, ints), you can use memmove() or memcpy() to copy them: (memmove is safe if the memory blocks overlap; memcpy isn't, but that's not a problem here) 现在,回答您的实际问题,由于我们正在处理简单的数据项(即int),因此您可以使用memmove()memcpy()复制它们:(如果内存块重叠,则mmmmove是安全的; memcpy不是,但这不是问题)

  one.index1 = (int *) malloc(5*sizeof(int)); // Line 2 
  memcpy(one.index1, a, sizeof(int) * 5); 

As for the efficency of memmove/memcpy, that's pretty much an unknown area. 至于memmove / memcpy的效率,这几乎是一个未知领域。 memmove does a bit more range checking then memcpy, so it'll be a hair slower the memcpy. memmove比memcpy做更多的范围检查,因此会比memcpy慢一点。 As far memcpy vs a loop, hard to say. 至于memcpy vs一个循环,很难说。 memcpy has a bit more overhead, but it's called a lot , so compiler vendors have a guy who spends a lot of time making sure it's a fast as possible. memcpy有更多的开销,但它的开销很大 ,因此编译器供应商会花很多时间来确保它尽可能快。

Note however, given a small, fixed number of elements to copy, the fastest way to going to be to just copy them directly: 但是请注意,由于要复制的元素数量很少且固定,因此直接复制它们的最快方法是:

  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];

Some quibbles. 一些小问题。

Life's easier if you define functions before they're called (if they're in the same source file, that is); 如果在调用函数之前就定义了函数,那么生活会更轻松(如果它们在同一个源文件中); that way you don't need to worry about keeping declarations/definitions in sync. 这样,您就不必担心保持声明/定义同步。

Don't cast the result of malloc() . 不要转换malloc()的结果 As of C89, you don't need to, and doing so may suppress a useful diagnostic if you forget to #include stdlib.h or otherwise don't have a prototype for malloc() in scope (although newer compilers are catching this error even with the cast since it happens so bloody often). 从C89开始,您不需要这样做,并且如果您忘记#include stdlib.h或在范围内没有malloc()的原型,这样做可能会抑制有用的诊断(尽管较新的编译器正在捕获此错误)即使是演员表,因为它经常发生流血事件)。

Use the sizeof operator on the thing you're allocating, not a type; 对要分配的对象(而不是类型)使用sizeof运算符; again, it makes life simpler since you don't have to keep the declaration and malloc() calls in sync. 再次,它使工作变得更简单,因为您不必保持声明和malloc()调用保持同步。

If you want a function to modify a pointer argument, you must pass a pointer to that pointer: 如果要让函数修改指针参数,则必须将指针传递给该指针:

void doo(int **p)
{
  *p = realloc(*p, 5 * sizeof **p); 
}

Otherwise the change to the formal parameter p is not reflected in the actual parameter. 否则,形式参数p的更改不会反映在实际参数中。

Life's also easier if you abstract out your memory management functions; 如果您抽象出内存管理功能,生活也会更轻松; you can replace lines 2 and 3 with a single function call: 您可以使用单个函数调用替换第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;
}

which you call as 你称之为

one.index1 = copy(a, len);

You can use memmove. 您可以使用记忆。 Be sure to #include <string.h> at start. 确保在开始时#include <string.h>

Replace lines 2 & 3 by, 将第2和3行替换为

one.index1 = malloc( 5*sizeof(int) );
memmove(one.index1,a, 5*sizeof(int) );

For example, consider a & c here: 例如,在这里考虑a和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));

Now both a & c are individual pointers, pointing to "same data" & can be freed separately. 现在,a和c都是单独的指针,指向“相同数据”,并且可以分别释放。

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

Is this new method more efficient? 这种新方法更有效吗? Practically, it is. 实际上是这样。 Compare the time it took for the program to run: (I have used long long type instead of int, to get the noticeable time difference) 比较程序运行所需的时间:(我使用long long类型而不是int来获得明显的时差)

Old method: 旧方法:

$ time ./a.out

real    0m0.249s
user    0m0.178s
sys     0m0.070s

New method: 新方法:

$ time ./a.out

real    0m0.164s
user    0m0.095s
sys     0m0.068s

You can use the memmove/memcpy function which is likely to be highly optimized: 您可以使用可能高度优化的memmove / memcpy函数:

const size_t size = 5*sizeof(int);
one.index = (int *) malloc(size);
memcpy(one.index, a, size);

Of course, you can wrap this into a function: 当然,您可以将其包装为一个函数:

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);

It depends on what specifically you want to avoid about lines 2 ond 3. If you want to avoid the loop, use memcpy, although most compilers should replace your loop with code equivalent to a memcpy call. 这取决于您要在第2行和第3行中特别避免的事情。如果要避免循环,请使用memcpy,尽管大多数编译器应使用等效于memcpy调用的代码替换循环。 If you want a one-liner operation, you can write a static function that takes the address of one.index1, the size of the array a, and a as arguments. 如果要进行单线操作,则可以编写一个静态函数,该函数采用地址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;
}

Don't forget to check if malloc returns NULL! 不要忘记检查malloc是否返回NULL!

If you want to avoid the call to malloc, I think the only option would be to have a chunk of memory set aside that you manage manually. 如果您想避免调用malloc,我认为唯一的选择是留出一部分内存,您可以手动管理。 It's almost never worth it to try to manage memory yourself, though. 但是,尝试自己管理内存几乎绝对不值得。

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

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