简体   繁体   English

memcpy或memmove可以返回与dest不同的指针吗?

[英]Can memcpy or memmove return a different pointer than dest?

The function memmove is defined like this: 函数memmove定义如下:

void *memmove(void *dest, const void *src, size_t n);

In the Linux manual page, it says: 在Linux手册页中,它说:

RETURN VALUE 返回值
The memmove() function returns a pointer to dest. memmove()函数返回指向dest的指针。

Why isn't the function just defined as void memmove(…) when it always returns one of the input parameters? 当函数总是返回其中一个输入参数时,为什么函数只被定义为void memmove(…) Can the return value be different from dest ? 返回值可以与dest不同吗?

Or is the return value really always dest and it is just done to be able to compose the function in some creative ways? 或者是返回值真的总是dest ,它只是做是为了能够撰写的功能在一些创造性的方式?

memmove will never return anything other than dest . memmove永远不会返回除dest之外的任何东西。

Returning dest , as opposed to making memmove void, is useful when the first argument is a computed expression, because it lets you avoid computing the same value upfront, and storing it in a variable. 当第一个参数是计算表达式时,返回dest而不是使memmove void是有用的,因为它允许您避免先前计算相同的值,并将其存储在变量中。 This lets you do in a single line 这使您可以在一行中完成

void *dest = memmove(&buf[offset] + copiedSoFar, src + offset, sizeof(buf)-offset-copiedSoFar);

what you would otherwise need to do on two lines: 你需要在两行上做什么:

void *dest = &buf[offset] + copiedSoFar;
memmove(dest, src + offset, sizeof(buf)-offset-copiedSoFar);

As per C11 , chapter §7.24.2.1 and §7.24.2.2 根据C11 ,章节§7.24.2.1和§7.24.2.2

void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

[...] The memcpy function returns the value of s1 . [...] memcpy函数返回s1的值。

and, 和,

void *memmove(void *s1, const void *s2, size_t n);

[...] The memmove function returns the value of s1 . [...] memmove函数返回s1的值。

So, the functions will always return the pointer to the destination buffer, that's by design. 因此,函数将始终返回指向目标缓冲区的指针,这是设计的。

Now coming to the why part, many functions are designed this way to make chaining of function calls possible. 现在来到为什么部分,许多函数都是这样设计的,以使函数调用链接成为可能。 That way, you can have a call to memmove() as an argument to another function, where the copied value ( ie, the pointer to dest ) is going to be of some use. 这样,您可以调用memmove()作为另一个函数的参数,其中复制的值( 即指向dest的指针 )将会有一些用处。

For example, you can write the shorter one 例如,您可以编写较短的一个

 puts(memmove(dest_buffer, src_buffer, welcome_message_size));

instead of the longer one 而不是更长的一个

 memmove(dest_buffer, src_buffer, welcome_message_size);
 puts(dest_buffer);

The idiom of returning the exact value of one of the arguments (of pointer type) exists in order to support "chained" function calls (also see strcpy , strcat etc). 返回其中一个参数(指针类型)的确切值的习惯用法是为了支持“链式”函数调用(也见strcpystrcat等)。 It allows you to write some repetitive code as a single expression statement instead of splitting it into multiple statements. 它允许您将一些重复代码编写为单个表达式语句,而不是将其拆分为多个语句。 For example 例如

char buffer[1024];
printf("%s\n", strcat(strcat(strcpy(buffer, "Hello"), " "), "World"));

struct UserData data_copy;
some_function(memcpy(&data_copy, &original_data, sizeof original_data));

Even if you don't like this style of organizing code and prefer doing the same through multiple statements, the overhead of returning an [unnecessary] pointer value is virtually non-existent. 即使您不喜欢这种组织代码的方式并且更喜欢通过多个语句执行相同的操作,返回[不必要的]指针值的开销几乎不存在。

One can even say that the value of this idiom increased a bit after the introduction of compound literals in C99. 甚至可以说,在C99中引入复合文字后,这个习语的价值有所增加。 With compound lterals this very idiom allows one to write the same code without introducing a named intermediate variable 使用复合lterals这个非常成语允许人们在不引入命名中间变量的情况下编写相同的代码

printf("%s\n", strcat(strcat(strcpy((char [1024]) { 0 }, "Hello"), " "), "World!"));

some_function(memcpy(&(struct UserData) { 0 }, &original_data, sizeof original_data));

which makes sense since in most cases that named variable is supposed to be short-lived, is not needed afterwards, and only clutters the namespace. 这是有道理的,因为在大多数情况下,命名变量应该是短命的,之后不需要,并且只会混淆命名空间。

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

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