简体   繁体   English

指针转换为char *数组

[英]Pointer cast into char* array

I'm fairly new to C++ and I'm having difficulty wrapping my head around what is going on in the final line of the below: 我是C ++的新手,我很难理解下面最后一行中发生的事情:

int numToSend = bs->GetSize();
char *  tBuf = new char[NUM_LENGTH_BYTES + numToSend];
*(WORD*)tBuf = htons((WORD)numToSend);

So htons is returning a u_short or WORD, but the cast on tBuf is somewhat confusing to me. 因此htons返回的是u_short或WORD,但是tBuf的强制转换对我来说有些混乱。 Is it something along the lines of "the value pointed to by tBuf is cast as a WORD pointer and assigned the return from htons"? 是否遵循“将tBuf指向的值转换为WORD指针并分配了htons的返回值”的含义?

I believe this is a fairly unsafe operation in most cases, what would be the best practice here? 我认为这在大多数情况下是相当不安全的操作,那么最佳做法是什么?

It may not be a recommended practice, but AFAIK, it is safe. 可能不建议这样做,但是AFAIK是安全的。 It is true that in general, taking a pointer to P, casting it to a pointer to Q and using it as a pointer to Q leads to undefined behaviour. 的确,通常,采用指向P的指针,将其转换为指向Q的指针并将其用作指向Q的指针会导致不确定的行为。 Here it looks even worse, because the alignment requirement of char are known to be the weakest possible. 这里看起来更糟,因为已知char的对齐要求是最弱的。

But the char * tBuf pointer has been obtained through a new expression. 但是char * tBuf指针是通过新表达式获得的。 Such a new expression internally rely on a allocation function to obtain storage, and draft n4296 for c++14 says in 3.7.4.1 Allocation functions [basic.stc.dynamic.allocation] §2: 这样的新表达式在内部依赖于分配函数来获取存储,并且针对c ++ 14的草稿n4296在3.7.4.1分配函数[basic.stc.dynamic.allocation]§2中说:

The allocation function attempts to allocate the requested amount of storage. 分配功能尝试分配请求的存储量。 If it is successful, it shall return the address of the start of a block of storage whose length in bytes shall be at least as large as the requested size... The pointer returned shall be suitably aligned so that it can be converted to a pointer of any complete object type with a fundamental alignment requirement (3.11) and then used to access the object or array in the storage allocated (until the storage is explicitly deallocated by a call to a corresponding deallocation function). 如果成功,它将返回一个存储块开始的地址,该存储块的字节长度至少应等于请求的大小...返回的指针应适当对齐,以便可以将其转换为具有基本对齐要求(3.11)的任何完整对象类型的指针,然后用于访问已分配存储中的对象或数组 (直到通过调用相应的释放函数显式释放该存储)。

So this line *(WORD*)tBuf = htons((WORD)numToSend); 所以这行*(WORD*)tBuf = htons((WORD)numToSend); only does perfectly defined operations: 仅执行完美定义的操作:

  • convert numToSend from an integer type to an unsigned type, and 4.7 Integral conversions [conv.integral] says: numToSend从整数类型转换为无符号类型,并且4.7积分转换[conv.integral]说:

    1. A prvalue of an integer type can be converted to a prvalue of another integer type... 整数类型的prvalue可以转换为另一种整数类型的prvalue ...

    2. If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type) 如果目标类型是无符号类型,则结果值是与源整数一致的最小无符号整数(取模2n,其中n是用于表示无符号类型的位数)

  • call htons with a WORD or uint16_t as parameter to return a uint16_t or WORD 使用WORD或uint16_t作为参数调用htons以返回uint16_t或WORD

  • converts a pointer obtained by new to a WORD * and uses that pointer to access the object in the storage allocated 将new获得的指针转换为WORD *并使用该指针访问分配的存储中的对象

Simply, the value of the first two bytes of the allocated array is now unspecified. 简而言之,现在未指定分配数组的前两个字节的值。 More exactly it is the byte representation of the WORD in the particular implementation. 更确切地说,它是特定实现中WORD的字节表示形式。

But it is still allowed to access the allocated array as a character array, even if the first bytes now contain a WORD, because it is explicitely allowed per the so called strict aliasing rule 3.10 Lvalues and rvalues [basic.lval] §10 : 但是,即使第一个字节现在包含WORD,也仍然允许将其作为字符数组访问,因为根据所谓的严格别名规则 3.10 Lvalues和rvalues [basic.lval]§10:

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined: 如果程序尝试通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
... ...
(10.8) — a char or unsigned char type. (10.8)-字符或无符号字符类型。


If the tBuf pointer had not been obtained through a new expression, the only correct way would have been to do a memcpy : 如果未通过新表达式获得tBuf指针,则唯一正确的方法是执行memcpy

WORD n_numToSend = htons(numToSend);
memcpy(tBuf, &n_numToSend, sizeof(WORD));

As this one is allowed for any pointer provided the storage is big enough, it is what I would call the recommended practice. 由于只要存储空间足够大,任何指针都可以使用此指针,这就是我所说的推荐做法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM