2016-09-20 55 views
1
uint32_t u32 = 0; 
uint16_t u16[2]; 
static_assert(sizeof(u32) == sizeof(u16), ""); 
memcpy(u16, &u32, sizeof(u32)); // defined? 
// if defined, how to we access the data from here on? 

这是定义的行为吗?如果是这样,在memcpy之后我们可以使用什么类型的指针来访问目标数据?从一种类型到另一种类型的memcpy。之后我们如何访问目的地?

我们必须使用uint16_t*,因为那适用于型号是u16

或者我们必须使用uint32_t*,因为源数据的类型(由memcpy复制的源数据)是uint_32

(个人兴趣在C++ 11/C++ 14,但相关的语言,如C的讨论会很有趣也。)

+1

是否编译? – wally

+0

它现在确实:-)(我忘记了一个'&'和另一个错字) –

+1

你想知道CPU的字节顺序吗? –

回答

1

C++标准委托给C标准:

内容和报头<cstring>的含义是相同的C标准库头<string.h>

C标准规定:

7.24.1/3对于本节的所有功能,每一个字符应被解释为,如果它有类型无符号的字符(并因此每个可能的对象表示是有效并具有不同的值)。

所以,回答你的问题:是的,行为是定义的。

是的,uint16_t*是合适的,因为uint16_t是对象的类型。


不,源的类型无关紧要。

C++标准没有将对象指定为没有声明类型的对象或它将如何表现。我认为这意味着有效类型是为没有声明类型的对象定义的实现。

即使在C中,在这种情况下源并不重要。报价从C标准(草案N1570)更完整的版本,你很关心,重点煤矿:

6.5/6 [...]如果值被复制到没有声明类型的对象使用memcpy或memmove,或者将其作为字符类型的数组复制,则该访问的修改对象的有效类型以及不修改该值的后续访问是从中复制该值的对象的有效类型,如果有的话。 [...]

此规则不适用,因为在u16对象确实有一个声明的类型

+0

一个小的跟进:对象的'声明类型',如果它有一个,永远不会改变?一个对象永远不会失去或获得'声明类型'?但是“有效类型”在某些情况下可以改变? –

+1

@AaronMcDaid声明的类型不会更改。如果对象声明了类型,那么它也是有效类型 - 它不会改变。如果没有声明类型,则可以获得或更改有效类型。 – user2079303

+0

我现在认为,如果在这里关于“声明”和“有效”类型的评论被引入到每个答案的开头,那么在Stack Overflow的其他问题上,严格别名答案的很大一部分会更有意义。 –

0

难道这behavio [U] R所规定?

是的。 memcpy进入吊舱是明确的,你确保了尺寸是正确的。

我们必须使用uint16_t*,因为那适合声明的类型u16

是的,当然。 u16是一个由两个uint16_t组成的数组,因此它必须按照这样的方式访问。通过严格别名规则访问它通过uint32_t*将是未定义的行为。

不管源类型是什么。重要的是你有一个uint16_t[2]类型的对象。


在另一方面,

uint32_t p; 
new (&p) uint16_t(42); 
std::cout << p; 

是不确定的行为,因为现在有不同的类型,其使用寿命已经开始在&p的对象,我们通过它访问错误的类型。

+0

有一件让我担心的事情是C语言标准中有一些句子暗示我的类型是'uint32_t',例如“[类型变成] ...从中复制值的对象的有效类型...“。我没有任何标准文档可供使用,我所能做的就是复制和粘贴我在网上找到的东西 - 我在这里找到了这个句子:http://stackoverflow.com/questions/30970251/what-is-the-effective类型的对象,由memset编写 –

+0

@AaronMcDaid C++不是C. – Barry

+0

除非C++明确声明它*是* C,在某些情况下。 (请参阅user2079303的答案)。 –

相关问题