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);
为了支持“链接”函数调用(也参见strcpy
, strcat
等),返回其中一个参数(指针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应该是短命的,事后不需要,只会混乱命名空间。