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

函数memmove是这样定义的:

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

在Linux手册页中,它说:

返回值
memmove()函数返回一个指向dest的指针。

当它总是返回一个input参数时,为什么不把函数定义为void memmove(…) ? 返回值可能与dest不同吗?

还是返回值真的总是dest ,而且只是为了能够用一些创造性的方式来编写函数呢?

memmove永远不会返回除dest以外的任何东西。

当第一个参数是一个计算expression式时,返回dest是相当有用的,因为它可以避免先前计算相同的值,并将其存储在一个variables中。 这可以让你在一个单一的行

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

你需要做两行:

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

根据C11 ,章节7.24.2.1和7.24.2.2

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

memcpy函数返回s1的值。

和,

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

memmove函数返回s1的值。

所以,函数将总是返回指向目标缓冲区的指针,这是devise的。

现在来谈谈为什么部分,许多函数被devise为使函数调用的链接成为可能。 这样,你可以调用memmove()作为另一个函数的参数,在这个函数中复制的值( 即指向dest的指针 )将会被使用。

例如,您可以编写较短的一个

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

而不是更长的一个

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

为了支持“链接”函数调用(也参见strcpystrcat等),返回其中一个参数(指针types)的确切值的习惯用法存在。 它允许你写一些重复的代码作为一个单一的expression式语句,而不是把它分成多个语句。 例如

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

即使你不喜欢这种组织代码的风格,并且喜欢通过多个语句来做同样的事情,返回一个[不必要的]指针值的开销实际上是不存在的。

甚至可以说在C99中引入复合文字后,这个习语的价值有所提高。 使用复合lterals这个非常习惯使人们能够编写相同的代码,而不需要引入一个命名的中间variables

 printf("%s\n", strcat(strcat(strcpy((char [1024]) { 0 }, "Hello"), " "), "World!")); some_function(memcpy(&(struct UserData) { 0 }, &original_data, sizeof original_data)); 

这是有道理的,因为在大多数情况下,命名variables应该是短命的,事后不需要,只会混乱命名空间。