实现`memcpy()`:需要`unsigned char *`,还是`char *`? [英] Implement `memcpy()`: Is `unsigned char *` needed, or just `char *`?

查看:548
本文介绍了实现`memcpy()`:需要`unsigned char *`,还是`char *`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现memcpy()的版本,以便能够与volatile一起使用. 使用char *是否安全?我是否需要unsigned char *?

I was implementing a version of memcpy() to be able to use it with volatile. Is it safe to use char * or do I need unsigned char *?

volatile void *memcpy_v(volatile void *dest, const volatile void *src, size_t n)
{
    const volatile char *src_c  = (const volatile char *)src;
    volatile char *dest_c       = (volatile char *)dest;

    for (size_t i = 0; i < n; i++) {
        dest_c[i]   = src_c[i];
    }

    return  dest;
}

如果缓冲区的任何单元中的数据为> INT8_MAX(我认为可能是UB),我认为unsigned对于避免溢出问题应该是必需的.

I think unsigned should be necessary to avoid overflow problems if the data in any cell of the buffer is > INT8_MAX, which I think might be UB.

推荐答案

从理论上讲,您的代码可能在禁止签名的char中使用一位模式的计算机上运行.它可能使用负整数的"1"补码或正负号表示,其中一个位模式将被解释为带负号的0.即使在二进制补码体系结构上,该标准也允许实现将负整数的范围限制为INT_MIN == -INT_MAX,尽管我不知道有任何实际的机器这样做.

In theory, your code might run on a machine which forbids one bit pattern in a signed char. It might use ones' complement or sign-magnitude representations of negative integers, in which one bit pattern would be interpreted as a 0 with a negative sign. Even on two's-complement architectures, the standard allows the implementation to restrict the range of negative integers so that INT_MIN == -INT_MAX, although I don't know of any actual machine which does that.

因此,根据§ 6.2.6.2p2,可能存在一个带符号的字符值,实现可以将其视为陷阱表示形式:

So, according to §6.2.6.2p2, there may be one signed character value which an implementation might treat as a trap representation:

[负整数的表示形式]中的哪些适用于实现定义,符号位为1且所有值位为零的值(对于前两个[符号幅度和二进制补码])还是带符号位和所有值位1(表示1的补码)是陷阱表示形式或正常值.如果是正负号,幅度和1的补码,则如果此表示形式是正常值,则称为负零.

(字符类型不能有任何其他陷阱值,因为§ 6.2.6.2要求signed char不具有任何填充位,这是可以形成陷阱表示形式的唯一其他方法.出于相同的原因,没有位模式是unsigned char的陷阱表示.)

(There cannot be any other trap values for character types, because §6.2.6.2 requires that signed char not have any padding bits, which is the only other way that a trap representation can be formed. For the same reason, no bit pattern is a trap representation for unsigned char.)

因此,如果此假设机器具有对char进行签名的C实现,则通过char复制任意字节可能涉及复制陷阱表示.

So, if this hypothetical machine has a C implementation in which char is signed, then it is possible that copying an arbitrary byte through a char will involve copying a trap representation.

对于除char(如果恰好是带符号)和signed char以外的带符号整数类型,读取作为陷阱表示形式的值是未定义的行为.但是§ 6.2.6.1/5允许仅用于字符类型读取和写入这些值:

For signed integer types other than char (if it happens to be signed) and signed char, reading a value which is a trap representation is undefined behaviour. But §6.2.6.1/5 allows reading and writing these values for character types only:

某些对象表示形式不必表示对象类型的值.如果对象的存储值具有这种表示形式,并且由不具有字符类型的左值表达式读取,则该行为是不确定的.如果这种表示是由副作用产生的,该副作用通过不具有字符类型的左值表达式修改对象的全部或任何部分,则该行为是不确定的.这样的表示称为陷阱表示. (添加了强调)

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined. Such a representation is called a trap representation. (Emphasis added)

(第三句话有点笨拙,但为简化起见:将值存储到内存中是修改所有对象的副作用",因此也是允许的.)

(The third sentence is a bit clunky, but to simplify: storing a value into memory is a "side effect that modifies all of the object", so it's permitted as well.)

简而言之,由于这个异常,您可以在memcpy的实现中使用char,而不必担心不确定的行为.

In short, thanks to that exception, you can use char in an implementation of memcpy without worrying about undefined behaviour.

但是,strcpy并非如此. strcpy必须检查结尾的NUL字节以终止一个字符串,这意味着它需要将从内存中读取的值与0进行比较.比较运算符(实际上是所有算术运算符)首先对其操作数执行整数提升,将char转换为int.据我所知,陷阱表示的整数提升是不确定的行为,因此在假设计算机上运行的假设C实现中,您需要使用unsigned char来实现strcpy.

However, the same is not true of strcpy. strcpy must check for the trailing NUL byte which terminates a string, which means it needs to compare the value it reads from memory with 0. And the comparison operators (indeed, all arithmetic operators) first perform integer promotion on their operands, which will convert the char to an int. Integer promotion of a trap representation is undefined behaviour, as far as I know, so on the hypothetical C implementation running on the hypothetical machine, you would need to use unsigned char in order to implement strcpy.

这篇关于实现`memcpy()`:需要`unsigned char *`,还是`char *`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆