Mar*_*ing 38 c return-value function-call memmove
该函数memmove定义如下:
void *memmove(void *dest, const void *src, size_t n);
在Linux手册页中,它说:
返回值
memmove()函数返回指向dest的指针.
为什么函数只是定义为void memmove(…)总是返回其中一个输入参数?返回值可以与dest?不同?
或者返回值是否总是dest如此,只是能够以某种创造性的方式组合功能?
das*_*ght 42
memmove将永远不会返回任何其他东西dest.
当第一个参数是计算表达式时,返回dest而不是创建memmovevoid是有用的,因为它允许您避免预先计算相同的值,并将其存储在变量中.这使您可以在一行中完成
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);
Sou*_*osh 26
根据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.
因此,函数将始终返回指向目标缓冲区的指针,这是设计的.
现在谈到原因部分,许多函数都是以这种方式设计的,以使函数调用链接成为可能.这样,您可以调用memmove()另一个函数作为参数,其中复制的值(即指向dest)将具有一定的用途.
例如,您可以编写较短的一个
 puts(memmove(dest_buffer, src_buffer, welcome_message_size));
而不是更长的一个
 memmove(dest_buffer, src_buffer, welcome_message_size);
 puts(dest_buffer);
AnT*_*AnT 13
返回的(指针类型的)一个参数的精确值的成语以便存在支持"链接"函数调用(也参见strcpy,strcat等).它允许您将一些重复代码编写为单个表达式语句,而不是将其拆分为多个语句.例如
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这个非常成语允许一个人编写相同的代码而不引入一个命名的中间变量
printf("%s\n", strcat(strcat(strcpy((char [1024]) { 0 }, "Hello"), " "), "World!"));
some_function(memcpy(&(struct UserData) { 0 }, &original_data, sizeof original_data));
这是有道理的,因为在大多数情况下,命名变量应该是短命的,之后不需要,并且只会混淆命名空间.