【问题标题】:Casting C string to unsigned char pointer将 C 字符串转换为无符号字符指针
【发布时间】:2011-11-14 13:47:19
【问题描述】:

我正在使用许多字节编译一个低级代码。在某些情况下,我可以很方便地使用双引号括起来的旧 C 字符串来定义。

但是当使用 gcc 或 g++ 编译时(不知道其他编译器的行为),它一直困扰着我的尖字符串符号。

基本上在我写这个的时候

const unsigned char & refok = *"ABCDEFGHI";

编辑:好的,上面的代码实际上并不能正常工作,因为理论上它只是保留对字符串第一个字符的副本的引用。由于优化,它实际上允许使用某些编译器访问所有字符串,但可能随时中断。

或者这个

const unsigned char oktoo[10] =
    {'A','B','C','D','E','F','G','H','I',0};

编译器什么也没说。

但它肯定拒绝这个:

const unsigned char * bad = "ABCDEFGHI";

有消息

error: invalid conversion from 
   ‘const char*’ to ‘const unsigned char*’
   [-fpermissive]

这甚至不是警告,而是错误

我想知道为什么这个问题比使用引用或将单个字符从有符号字符转换为无符号字符时更成问题?还是我错过了什么?

【问题讨论】:

  • 您的问题被标记为 C 和 C++ 的主题,C 和 C++ 差异很大。请删除您不使用的语言的标签。
  • @Complicatedseebio - 因为看起来他并不急于这样做,所以您可以添加一个 C 答案,并说明它是针对 C 而不是 C++(就像接受的答案是,我相信)。
  • @Complicatedseebio:是的,C 答案会很好。任何人都可以看到上面的虚假参考资料,我的建议是使用 C++ 编写的。我的部分问题是,完全相同的代码在使用 C 编译时有效,而在使用 C++ 时出现编译错误。

标签: c++ casting


【解决方案1】:

我认为你错过了很多 的东西!

第一行可能与您的想法完全不同。 (这涉及到临时的转换和延长寿命。)

第二行从大括号初始化器中的相应字符初始化每个无符号字符。

在第三行中,编译器是正确的:字符串文字的类型为const char *,一般不能将T* 转换为U*

请注意,标准明确要求charunsigned charsigned char不同的 类型。这里的推理是char 应该是平台的本机字节类型,而另外两个是显式无符号和有符号整数类型。无符号/有符号类型用于代数运算,而裸类型用于与系统交互(例如命令行参数和文件 I/O)。

【讨论】:

  • 有趣。使用reinterpret_cast <unsigned char const *> 绕过它有多安全?
  • 我认为没关系。类型双关语规则明确排除所有类型的 char 指针。 (只要确保保持常数,但你已经做到了。)事实上,我一直这样做,因为我希望我的数据是unsigned char,但我确实从文件中读取它并将其写入文件。
  • @kriss:再读一遍:本机类型是签名的,它是未指定的并且取决于平台。所有的标准要求是这三种 char 类型是 distinct,因此它们的指针不兼容。关于标准要求,除了“这就是语言的要求”之外,没有什么可以说的了。
  • 本机 char 未明确签名或未签名。你会得到与 const signed char * bad = "ABCDEFGHI"; 相同的错误。这是某种“可能已签名,这不关你的事”字符。
  • @kriss: ...也就是说,类型(不是它们的指针!)在任何整数类型都可转换的程度上是可转换的。当然,您必须注意那里的签名问题。例如。如果值太大,将 unsigned char 转换为 signed char 可能是未定义(不仅仅是未指定)行为;而将有符号转换为无符号始终是明确定义的。这应该可以真正解释您观察到的一切,但请随时提出更具体的问题。
【解决方案2】:

允许数值类型之间的隐式转换;这就是前两个正在做的事情。不允许不同指针类型之间的隐式转换(除了将派生类指针转换为基类指针)。

请注意,第一个 not 给出了对数组第一个字符的引用。它创建该字符的临时副本,转换为unsigned char 类型,并将引用绑定到该字符,从而将临时的生命周期延长到引用的生命周期。

第二个将初始化列表中的每个char 转换为unsigned char 数组元素。

第三次尝试将const char *转换为const unsigned char *;因为charunsigned char 是不同的类型,所以不允许隐式指针转换。

【讨论】:

  • 好的,所以我猜第一个版本只是伪造的,并且仅在访问后续字符时才有效,因为编译器正在优化临时的重新分配。绝对应该避免。从今以后,如果我想对一堆数据使用无符号字符,我就会陷入语法噪音。
猜你喜欢
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多