我想使用 memcpy 在可能包含任意类型的数组中进行“类型不可知交换”。为什么它需要一个 const src 指针?
我写了自己的版本:
void copyBytes(char *x, char *y, int howMany){
int i;
for(i = 0; i<howMany; i++){
*(x+i) = *(y+i);
}
}
我的版本有问题吗?
我想使用 memcpy 在可能包含任意类型的数组中进行“类型不可知交换”。为什么它需要一个 const src 指针?
我写了自己的版本:
void copyBytes(char *x, char *y, int howMany){
int i;
for(i = 0; i<howMany; i++){
*(x+i) = *(y+i);
}
}
我的版本有问题吗?
我的版本有问题吗?
我会这么说。这是一个批评。
void copyBytes(char *x, char *y, int howMany)
首先,您的指针是,这意味着除需要显式转换之外的char *
任何指针类型。char *
您应该使用void *
, 指针类型被隐式转换为。
uint16_t a, b;
copyBytes(&a, &b, sizeof(a)); // &a and &b are uint16_t*, not char*.
其次,来源 ,y
不是const
,这意味着如果您传递const
来源,您将收到警告。
char buf[512];
const char str[] = "Hello world"; // Contents of string are constant.
copyBytes(buf, str, sizeof(str)); // With your code, this produces a warning.
第三,howMany
是有符号的,意思是你可以传递一个负值。
我会推荐这样的签名(顺便说一下,这与 非常相似memcpy
):
void copyBytes(void *x, const void *y, size_t howMany)
第四个批评... libcmemcpy
可能会得到更好的优化,使用大于字节的单元、特定于平台的性能技巧(例如:内联汇编、x86 上的 SSE)等。memmove
当缓冲区重叠。
总结:为学习目的自己编写这些例程很好,但使用 C 库通常会好得多。
“要求”?“要求”是一个错误的词。memcpy
不需要src指针const
。它允许一个const
src 指针。允许const
src 指针是一个较弱的规范,然后需要一个非常量 src 指针。它扩展了功能的适用性,而不是限制它。
需要一个非常量 src 指针会限制它的适用性memcpy
——你不能将指向const
数据的指针传递给你的函数(除非你使用丑陋的演员表)。为什么要提出这样的要求?memcpy
不会修改 src 数据,因此允许将常量数据用作 src 的 src 是完全合乎逻辑的memcpy
。这就是为什么memcpy
将 src 指针声明为const
.
在这种情况下,“require”一词实际上适用于您的版本。你的版本需要非常量指针作为 src 指针。并且由于这个额外的(并且完全不必要的)要求,您的版本不如memcpy
. 例如
const char src_data[3] = { 1, 2, 3 };
char dst_data[3];
memcpy(dst_data, src_data, sizeof dst_data); // Works
copyBytes(dst_data, src_data, sizeof dst_data); // Doesn't even compile
函数memcpy
不会修改源内存。这意味着它不需要非常量指针,它允许常量指针和非常量指针。这不是对参数的限制,也不是对函数的适用性的限制。您可以在那里传递任何有效的数据指针。
这被编译器称为隐式转换。在您的特定情况下,const
它是"Qualification conversion"。
unqualified type can be converted to const
不允许从 const 指针到指针的相反隐式转换。注意这里的“隐含”一词。这意味着func(void *pointer)
比 更具限制性func(void const *pointer)
。
如果您省略const
限定符,您将利用编译器强加的类型安全性。编译器会警告您或其他人,传入 const 指针不是一个好主意。
如果您const
在函数声明中使用限定符,则您承诺不会在那里修改数据。这对程序员来说是一个很好的提示,并提高了代码的可读性。然而,这只是一个承诺。一个糟糕的函数可能会通过在函数体中抛出 const-ness 来违反承诺。这在技术上是可行的,但很糟糕。