字节和字符之间的转换存在一个小问题。我想避免潜在的 UB,但我不确定它们是否会发生。
数据被读入std::vector<std::uint8_t>
,然后,就我而言,必须分成两部分:其中一个始终是文本,第二个是文本或二进制。
我使用了一个特定的分隔符,例如,像这样:
std::string delimiter{"delimiter"};
auto delim_iter = std::search(
byte_vector.begin(), byte_vector.end(),
delimiter.begin(), delimiter.end()
);
delim_iter += delimiter.size();
std::string char_part{byte_vector.begin(),delim_iter};
如您所知,char
根据实现,它可以是signed
, 或unsigned
. 因此,我不清楚如何正确地做到这一点以避免出现问题。
例如,在使用时,std::transform
建议传递一个 lambda,它需要unsigned char
:
std::transform(
string.begin(), string.end(), string.begin(),
[](unsigned char ch) { return std::tolower(ch); }
);
这里有任何潜在的问题吗?能以某种方式解决吗?谢谢你。
任何整数类型都可以隐式转换为任何其他整数类型。
如果目标类型是
bool
,则将空值转换为false
,将任何非空值转换为true
。如果目标类型是无符号整数类型,则使用模运算将该值转换为目标类型。
如果目标类型是有符号整数类型,并且要转换的值可以由目标类型表示,那么它不会被转换改变。如果要转换的值不能由目标类型表示,则
从 C++20 开始,您可以确定
其中 types
T1
和 是以下列表中的任何T2
类型T3
char
,signed char
,unsigned char
,std::int8_t
,std::uint8_t
.上述陈述源于模算术的属性和整数类型的二进制补码表示的使用。
在 C++20 之前,没有这样的保证。在不使用二进制补码有符号整数类型来表示的实现中,肯定应该违反上述某些陈述。但是要面对这样的实现是一项非常艰巨的工作。通常,在实践中,上述陈述得到满足。
此外,在 C++20 之前,即使仍使用附加代码,标准仍将转换的结果留给
(std::int8_t)255
实现的摆布。但是,通常观察到的行为与 C++20 一致。综上所述,我们有
此代码不会生成未定义的行为。但是因为 由于该函数
std::search()
使用运算符来比较值==
,因此搜索结果可能取决于类型是有char
符号还是无符号。示例:如果您需要检查精确的逐字节对应关系,那么您可以使用
search()
采用二进制谓词的函数版本,在该版本中实现参数到某些常见类型的显式转换。例如,像这样:从 C++20 开始,以下代码的结果是明确的:
type 的值
std::uint8_t
将被转换为 typechar
。位模式不会随着这种转换而改变,它的解释方式会改变。反向转换 (char
->std::uint8_t
) 将恢复原始值。在 C++20 之前,它很可能也可以工作。
这里
当 lambda 被调用时,它将被转换
char
为unsigned char
. 然后调用std::tolower()
将转换unsigned char
为int
.该函数
std::tolower()
有一个类型参数int
。但是,不能将类型表示的任何值int
传递给函数std::tolower()
。参数必须等于EOF
,或者必须可以按类型表示unsigned char
。否则,函数的行为是未定义的。因为 传递了 type 的值
unsigned char
,那么应该没有任何问题。尽管该标准允许实现类型值的unsigned char
范围比类型的非负值范围更宽的实现int
。(例如,如果unsigned char
和unsigned int
具有相同的表示)。那些。理论上未定义的行为在这里是可能的。为了我自己的安心,我只想添加一个编译时检查:调用的结果
std::tolower()
是类型int
。标准对这个函数返回的值的范围不是很清楚,但是假设它是EOF
(如果它EOF
作为参数传递的情况下)或者由unsigned char
.如前所述,转换
unsigned char
为char
C++20 以来的结果是唯一定义的。在这种情况下,它转换int
为char
,但int
存储了一个可表示的值unsigned char
,因此结果是等价的。最后的转换链
char
->unsigned char
->int
->char
。在这种特殊情况下,如果您不考虑类型unsigned char
和unsigned int
具有相同内部表示的实现,那么应该没有问题。