【问题标题】:Is It Legal to Cast Away the Sign on a Pointer?扔掉指针上的标志是否合法?
【发布时间】:2016-01-19 13:57:10
【问题描述】:

我正在使用 unsigned char*s 包含字符串的过时代码库。对于我的功能,我使用了strings,但是有一个问题:

我不能在旧代码的#include <cstring> 中使用任何东西。从string 复制到unsigned char* 是一个费力的过程:

unsigned char foo[12];
string bar{"Lorem Ipsum"};

transform(bar.cbegin(), bar.cbegin() + min(sizeof(foo) / sizeof(foo[0]), bar.size()), foo, [](auto i){return static_cast<unsigned char>(i);});
foo[sizeof(foo) / sizeof(foo[0]) - 1] = '\0';

如果我这样做,我是否会遇到未定义的行为或别名问题:

strncpy(reinterpret_cast<char*>(foo), bar.c_str(), sizeof(foo) / sizeof(foo[0]) - 1);
foo[sizeof(foo) / sizeof(foo[0]) - 1] = '\0';

【问题讨论】:

  • 这里需要跨平台吗?您是否愿意满足于在您当前平台上工作的东西,即使它可能严格是 C++ 标准中的 UB? char 保证与signed charunsigned char 之一具有相同的表示形式,即使在signed 的情况下,您也可能使用严​​格的ACSII 数据是安全的:[0,127]
  • @BeyelerStudios 是 ASCII。
  • @BeyelerStudios strncpy 已经帮我检查过了。
  • 措辞注意事项:您不能char*s 中存储任何风格的字符串。您将字符串存储在char arrays 中,并通过指针访问这些数组的内容,即char*s。混淆“数组”和“指针”会导致混乱。
  • @PeteBecker,这对我来说太过分了。这也不正确 - 我当然可以将字符串存储在 char* 中,而这从来都不是数组

标签: c++ c-strings strcpy reinterpret-cast unsigned-char


【解决方案1】:

[unsigned] char 的严格别名规则有一个明确的例外,因此在字符类型之间转换指针就可以了。

特别是在N3690 [basic.types] 中说任何可简单复制的对象都可以复制到charunsigned char 的数组中,如果然后复制回来,则值是相同的。它还说,如果您将相同的数组复制到第二个对象中,这两个对象是相同的。 (第二、三段)

[basic.lval] 表示通过charunsigned char 类型的左值更改对象是合法的。

我认为 BobTFish 在 cmets 中表达了对 charunsigned char 中的值是否放错位置的担忧。 “字符”值本质上是char 类型。您可以将它们存储在 unsigned char 中,稍后将它们用作 char - 但这已经发生了。

(我建议编写一些内联包装函数来降低整个事情的噪音,但我认为代码 sn-ps 是为了说明而不是实际使用。)

编辑:删除使用static_cast的错误建议。

Edit2:章节和诗句。

【讨论】:

  • 你不能这样做 static_cast&lt;char*&gt; 如此处所述:stackoverflow.com/questions/34878710/…
  • 称我为怀疑论者,但我肯定希望看到这方面的消息来源,尤其是在整个 static_cast 崩溃之后。
  • 是的。在上面看到您的评论并更改了我的答案(在您的评论出现之前!)
  • 有趣。我只是在想“宁愿让我对严格别名的断言受到质疑”。
  • 那是为了访问对象表示,不是吗? IE。您可以将指向任何对象的指针转换为(unsigned) char* 并返回,如果对象可轻松复制,则复制它。但是我看不到任何关于实际字符值相同的保证。 (除非charunsigned,这是实现定义)。
猜你喜欢
  • 2021-02-14
  • 2015-08-22
  • 2013-12-17
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 2018-05-01
相关资源
最近更新 更多