赋值:创建我自己的memcpy,为什么要将目的指针和源指针强制转换为unsigned char* 而不是char*?[duplicate]

guz6ccqo  于 2023-02-21  发布在  其他
关注(0)|答案(3)|浏览(181)
    • 此问题在此处已有答案**:

Implement memcpy(): Is unsigned char * needed, or just char *?(4个答案)
11天前关闭。
我试着创建我自己的C函数版本,当我看到memcpymemset时,我假设我应该将目的地和源指针转换为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;
}
3lxsmp7m

3lxsmp7m1#

这种情况并不重要,但是许多使用原始字节的人更喜欢显式指定unsigned char(或与stdint.h类型,uint8_t),以避免怪异,如果他们必须做数学与bytes. char has implementation-defined signedness,这意味着,当整数提升&通常的算术转换应用,高位被置位的char在有符号的情况下被视为负数,而在无符号的情况下被视为正数。
虽然对于给定的问题,这两种行为都不一定是错误的,但是行为可以在编译器之间、甚至在同一编译器上设置不同的标志时“更改”,这意味着您经常需要明确表示符号性,根据需要使用signed charunsigned char,并且99%的情况下,unsigned char的行为都是您想要的。所以人们倾向于默认使用它,即使它不是严格要求的。

wydwbb8l

wydwbb8l2#

在这种情况下没有特别的原因,主要是文体上的原因。
但一般来说,在处理原始数据时,最好始终坚持无符号算术,即:unsigned charuint8_t
char类型是有问题的,因为它具有实现定义的有符号性,因此在此类代码中应避免使用。Is char signed or unsigned by default?
注意:这是危险和不良的风格:

char *src_arr = (char *)src;

(And演员们把问题藏在地毯下面)
由于您正确地为src使用了"const correctness",因此正确的类型为:const char *src_arr;我会将代码更改为:

unsigned char *dest_arr = dest;
const unsigned char *src_arr = src;

对于初学者来说,一个很好的经验法则是"永远不要"使用强制转换。我是认真的。我们在初学者级别的程序中看到的所有强制转换中,大约90%都是错误的,在某种程度上是错误的。
顺便说一句(高级主题),memcpy的原型是有原因的:

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

指针上的restrict限定符告诉函数的用户"嘿,我指望你不要传递指向同一个对象的两个指针或可能重叠的指针"。这样做在不同的情况下会导致不同目标的问题,所以这是一个好主意。
用户传递重叠指针的可能性要比传递空指针的可能性大得多,因此,如果要对NULL进行缓慢而多余的错误检查,还应该对指针进行restrict限定。
如果用户传递了空指针,我会让函数崩溃,而不是用额外的分支来减慢它的速度,这在99%的用例中是毫无意义的膨胀。

tvokkenx

tvokkenx3#

为什么...是unsigned char*而不是char*
简短回答:因为当char为 * signed * 时,选择操作中的功能不同,并且C规范为str...()mem...()指定了类似unsigned char的功能。
"* 什么时候会有不同**
当一个函数(如memcmp()strcmp()等)比较顺序时,一个字节为负,另一个为正,这两个字节的顺序不同。〈1,但是当作为unsigned char查看时:255〉1.

    • 什么时候没有区别**

复制数据并比较是否相等时 * 1。

    • 非2的赞美**
  • 1在即将到来的C2x版本中,1的补码和符号幅度编码预计将被删除。在此之前,这些符号编码支持2个零。对于str...()mem...()函数,C指定数据访问为unsigned char。这意味着只有+0是 * 空字符 ,顺序取决于纯二进制, unsigned *,编码。

相关问题