【问题标题】:Is casting from TYPE* to unsigned char* allowed?是否允许从 TYPE*​​ 转换为 unsigned char*?
【发布时间】:2014-09-03 19:20:21
【问题描述】:

C99 - 特别是第 6.2.6.1 节第 4 段 - 声明允许将对象表示复制到 unsigned char 数组中:

struct {
    int foo;
    double bar;
} baz;
unsigned char bytes[sizeof baz];

// Do things with the baz structure.

memcpy(bytes, &baz, sizeof bytes);

// Do things with the bytes array.

我的问题:我们不能通过简单的转换来避免额外的内存分配和复制操作吗?例如:

struct {
    int foo;
    double bar;
} baz;
unsigned char *bytes = (void *)&baz;

// Do stuff with the baz structure.

// Do things with the bytes array.

当然,需要跟踪大小,但这首先是合法的,还是属于实现定义或未定义行为的领域?

我问是因为我正在实现类似于 qsort 的算法,并且我希望它适用于任何类型的任何数组,就像 qsort 一样。

【问题讨论】:

  • AFAIK, char 给所有东西起别名,所以应该没问题。
  • 视情况而定。通常你会很好,但我知道 GCC 有一个标志,它通过假设指向不同类型的指针不能是相同的内存空间来实现更好的优化。像这样的铸造,你将无法利用它。除非/直到这是一个性能瓶颈,否则我会避免它。
  • @Dave -fstrict-aliasing?不会伤害char
  • 反之则不好。这样就可以了。
  • @EOF 那是我想的那个。那么char就可以了吗?我找不到任何文档来检查一种或另一种方式...

标签: c void-pointers opaque-pointers


【解决方案1】:

6.5 表达式

[...]
6 访问其存储值的对象的有效类型是声明的类型 对象,如果有的话。87) 如果一个值通过 左值的类型不是字符类型,则左值的类型变为 该访问和不修改的后续访问的对象的有效类型 存储的值。如果一个值被复制到一个没有声明类型的对象中,使用 memcpy 或 memmove,或复制为字符类型的数组,则为有效类型 为该访问和后续访问不修改 value 是从中复制值的对象的有效类型(如果有的话)。为了 对没有声明类型的对象的所有其他访问,对象的有效类型是 只是用于访问的左值的类型。
7 一个对象的存储值只能由具有以下之一的左值表达式访问 以下类型:88)

  • 与对象的有效类型兼容的类型,
  • 与对象的有效类型兼容的类型的限定版本,
  • 对应于有效类型的有符号或无符号类型 对象,
  • 一种类型,它是有符号或无符号类型,对应于 对象的有效类型,
  • 一种聚合或联合类型,其中包括上述类型之一 成员(递归地包括子聚合或包含联合的成员),或
  • 一种字符类型

强调我的。因此,您可以将任何类型视为字符数组(unsigned char[]char[]signed char[])。

我还引用了第 6 段,因为它使相反的情况不适用。

【讨论】:

  • 换句话说,只要我可以保证任何字符类型的缓冲区中的数据与我正在转换的给定类型的对象表示完全匹配,就不需要复制操作.感谢您指出标准的相关部分;你真的为我澄清了这一点。
  • 不完全。如果将数据放入声明类型为char[] 的数组中,则不能将其作为结构体来引用。但如果你使用匿名记忆,你可以。
  • 匿名内存是通过malloc 或其他类似函数分配的内存,对吧?所以struct_ptr = (void *)char_buffer; 是不对的,因为char_buffer有效类型 是字符类型,它不是与结构类型兼容的类型。还是我错过了什么?
  • @ChronoKitsune:那是票,是的。不过,如果您使用匿名内存,也要小心对齐错误(malloc 等返回的任何块的开头对于任何类型都正确对齐)。
猜你喜欢
  • 2012-04-28
  • 2014-12-27
  • 1970-01-01
  • 2011-10-19
  • 2013-09-23
  • 2011-07-23
  • 2010-10-14
  • 2012-09-03
  • 1970-01-01
相关资源
最近更新 更多