我想使用一个函数,它需要这样的数据:

void process(char *data_in, int data_len);

所以它只是在处理一些字节.

但对于原始字节,我更喜欢使用"unsigned char"(只处理正0到255个值"感觉"更合适),所以我的问题是:

我是否始终可以安全地将unsigned char *传递到此函数中?

换句话说:

  • 是否保证我可以安全地在字符和未签名字符之间随意转换(强制转换),而不会丢失任何信息?
  • 我是否可以在不丢失任何信息的情况下,在指向char和未签名char的指针之间安全地进行转换(强制转换)?

奖励:C和C++的答案相同吗?

推荐答案

如果使用显式cast,简短的回答是肯定的,但要详细解释它,有三个方面需要考虑:

1) Legality of the conversion

static_cast<unsigned char*>(static_cast<void *>(data_in))

这可以缩写为(§5.2.10/7)

reinterpret_cast<unsigned char *>(data_in)

因为char是一种标准布局类型(§3.9.1/7,8和§3.9/9),且标志性不会改变对齐方式(§3.9.1/1).它也可以写成C风格的演员阵容:

(unsigned char *)(data_in)

同样,这是双向的,从unsigned*signed*,再回到unsigned*.此外,还可以保证,如果您将此过程单向应用,然后再反向应用,指针值(即指针指向的地址)不会发生更改(§5.2.10/7).

所有这些不仅适用于signed char *unsigned char *之间的转换,还分别适用于char */unsigned char *char */signed char *.(charsigned charunsigned char在形式上是三种截然不同的类型,§3.9.1/1.)

需要说明的是,使用三种强制转换方法中的哪一种并不重要,但必须使用其中一种.仅仅传递指针是行不通的,因为转换虽然合法,但不是标准转换,因此不会隐式执行(如果您try ,编译器将发出错误).

2) Well-definedness of the access to the values

如果程序试图通过除以下类型之一之外的glvalue种方式访问对象的存储值,则行为未定义:

  • [...]
  • 与对象的动态类型相对应的有符号或无符号类型,
  • [...]
  • charunsigned char型.

Therefore, accessing a signed char (or char) through an unsigned char* (or char) and vice versa is not disallowed by this rule – you should be able to do this without problems.

3) Resulting values
取消类型转换指针的引用后,是否可以使用所获得的值?重要的是要记住,上述指针的转换和取消引用相当于重新解释(而不是更改!)存储在字符地址的位模式.那么,当有符号字符的位模式被解释为无符号字符的位模式(反之亦然)时,会发生什么情况呢?

当从无符号变为有符号时,typical effect将是0到128之间的值,不会发生任何变化,128以上的值将变为负值.反过来类似:从有符号到无符号时,负值将显示为大于128的值.

但这一行为被"标准"定为isn't actually guaranteed.标准唯一保证的是,对于所有三种类型(charunsigned charsigned char),所有位(不一定是8位,btw)都用于值表示.因此,如果您将一个解释为另一个,复制几个副本,然后将其存储回原始位置,您可以确保不会丢失信息(按照您的要求),但是您不一定知道这些值的实际含义(至少不是以完全可移植的方式).

C++相关问答推荐

为什么我得到更多的256假阳性在PKZIP解密密钥验证?

以前版本的tty_ldisc_ops.ioctl()是否也需要文件参数?

在没有动态内存分配的情况下,用C语言最快地将各种数组复制到单个较大的数组中

进程已完成,退出代码为138 Clion

对重叠字符串使用MemMove

用C++实现余弦函数

如何在C-函数中混合使用C代码和ASM?

Tic-tac-toe:从文件加载存储

不同原型的危险C函数是可能的

-Wnonnull-Compare警告不是具有误导性吗?

如何在双向表中实现线程安全,每个条目仅使用4位,同时避免任何全局锁?

Linux/C:带有子进程的进程在添加waitid后都挂起

C语言中的指针和多维数组

在分配内存后使用指针是未定义的行为吗?

";错误:寄存器的使用无效;当使用-masm=intel;在gcc中,但在AT&;T模式

为什么程序在打印每个数字之前要等待所有输入?

cs50拼写器分配中的无限循环

malloc 属性不带参数

Makefile - 将 .o 文件放入子文件夹中

为什么 C 字符串并不总是等同于字符数组?