Selecting std :: vector <char> section in std :: array <char, n>, C ++ 11
Is the following code a violation of strict aliases or otherwise lead to undefined behavior in accordance with the C ++ 11 standard? Are there any better ways to achieve the same functionality?
void do_things(const std::array<char, 64> &block) { // ... } int main() { std::vector<char> buffer(64); do_things(reinterpret_cast<const std::array<char, 64> &>(buffer[0])); } TL; DR: Using const char * much less painful
edit: since sizeof(std::array<char, n>) not guaranteed to be n , I suggest the following:
void do_things(const char (&block)[64]) { // ... } int main() { std::vector<char> buffer(64); do_things(reinterpret_cast<char (&)[64]>(buffer[0])); } According to my understanding of aliases, this should not lead to undefined behavior and fix the semantics of transmitting an array of a fixed size. Do I understand correctly?
The strict rule of aliases applies to ยง3.10 [basic.lval] / p10, which ensures that
If a program tries to access the stored value of an object through a glvalue of a different than one of the following types, the behavior is undefined:
- dynamic type of object
- cv-qualified version of the dynamic type of an object,
- a type similar (as defined in 4.4) for the dynamic type of an object,
- a type that is a signed or unsigned type corresponding to a dynamic type of an object,
- a type that is a signed or unsigned type corresponding to the receipt version of the dynamic type of an object,
- an aggregate or union type that includes one of the above types among its elements or non-static data members (including, recursively, a sub-aggregate element or non-static data element or containing a union)
- [...]
Thus, access to an object of type char via a gl value of type std::array<char, N> does not violate this rule, because std::array<char, N> is an aggregate type that includes char as an element of a non-static data element summation.
However, you still cannot use anything with the resulting link without invoking undefined behavior due to another rule - ยง9.3.1 [class.mfct.non-static] / p2:
If a non-static member function of class
Xis called that is not of typeXor of a type derived fromX, the behavior is undefined.
It is also worth noting that no rule in the standard guarantees that sizeof(std::array<T, N>) == sizeof(T) * N The only standard guarantees are that std::array<T, N> is an aggregate type and can be initialized using the braced-init list containing up to N T s. Implementation is free to add additional materials.
Depending on what do_things needs, you may want to make your function iterators with random access or just a pointer. Alternatively, if you want to restrict your function to only std::vector and std::array s, you can write overloads that accept const refs and call the helper function with const char * , which does the actual work.
The new version does not violate the rules that I can think of, but it is a pretty bad design that requires reinterpret_cast be used almost every time you call your function. If you accidentally declared buffer as std::vector<std::string> or wrote buffer instead of buffer[0] , the compiler will happily compile your code without warning with potentially catastrophic results.