- 此问题在此处已有答案**:
Implement memcpy()
: Is unsigned char *
needed, or just char *
?(4个答案)
11天前关闭。
我试着创建我自己的C函数版本,当我看到memcpy
和memset
时,我假设我应该将目的地和源指针转换为char *
,然而,我看到很多例子中指针被转换为unsigned char *
,这是为什么呢?
void *mem_cpy(void *dest, const void *src, size_t n) {
if (dest == NULL || src == NULL)
return NULL;
int i = 0;
char *dest_arr = (char *)dest;
char *src_arr = (char *)src;
while (i < n) {
dest_arr[i] = src_arr[i];
i++;
}
return dest;
}
3条答案
按热度按时间3lxsmp7m1#
这种情况并不重要,但是许多使用原始字节的人更喜欢显式指定
unsigned char
(或与stdint.h
类型,uint8_t
),以避免怪异,如果他们必须做数学与bytes.char
has implementation-defined signedness,这意味着,当整数提升&通常的算术转换应用,高位被置位的char
在有符号的情况下被视为负数,而在无符号的情况下被视为正数。虽然对于给定的问题,这两种行为都不一定是错误的,但是行为可以在编译器之间、甚至在同一编译器上设置不同的标志时“更改”,这意味着您经常需要明确表示符号性,根据需要使用
signed char
或unsigned char
,并且99%的情况下,unsigned char
的行为都是您想要的。所以人们倾向于默认使用它,即使它不是严格要求的。wydwbb8l2#
在这种情况下没有特别的原因,主要是文体上的原因。
但一般来说,在处理原始数据时,最好始终坚持无符号算术,即:
unsigned char
或uint8_t
。char
类型是有问题的,因为它具有实现定义的有符号性,因此在此类代码中应避免使用。Is char signed or unsigned by default?注意:这是危险和不良的风格:
(And演员们把问题藏在地毯下面)
由于您正确地为
src
使用了"const correctness",因此正确的类型为:const char *src_arr;
我会将代码更改为:对于初学者来说,一个很好的经验法则是"永远不要"使用强制转换。我是认真的。我们在初学者级别的程序中看到的所有强制转换中,大约90%都是错误的,在某种程度上是错误的。
顺便说一句(高级主题),
memcpy
的原型是有原因的:指针上的
restrict
限定符告诉函数的用户"嘿,我指望你不要传递指向同一个对象的两个指针或可能重叠的指针"。这样做在不同的情况下会导致不同目标的问题,所以这是一个好主意。用户传递重叠指针的可能性要比传递空指针的可能性大得多,因此,如果要对
NULL
进行缓慢而多余的错误检查,还应该对指针进行restrict
限定。如果用户传递了空指针,我会让函数崩溃,而不是用额外的分支来减慢它的速度,这在99%的用例中是毫无意义的膨胀。
tvokkenx3#
为什么...是
unsigned char*
而不是char*
?简短回答:因为当
char
为 * signed * 时,选择操作中的功能不同,并且C规范为str...()
和mem...()
指定了类似unsigned char
的功能。"* 什么时候会有不同**
当一个函数(如
memcmp()
,strcmp()
等)比较顺序时,一个字节为负,另一个为正,这两个字节的顺序不同。〈1,但是当作为unsigned char
查看时:255〉1.复制数据并比较是否相等时 * 1。
str...()
和mem...()
函数,C指定数据访问为unsigned char
。这意味着只有+0是 * 空字符 ,顺序取决于纯二进制, unsigned *,编码。