Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I safely convert struct of floats into float array in C++? [duplicate]

Tags:

c++

For example I have this struct

struct  A {
    float x;
    float y;
    float z;
};

Can I do this? A a; float* array = (float*)&a; And use a as float array?

like image 603
Semyon Avatar asked Aug 26 '17 17:08

Semyon


People also ask

Why float is not working in structure?

Why the problem use the float value use in structure? Since there no addressing pointer like '&' in scanf. It generates an error. No sir in gcc you can also link the float variable.

Can you make a float array in C?

You can't create an array with no static size. You can create an array like this on the stack, which is mostly when you have smaller arrays: float myarray[12]; it is created in the scope and destroyed when that scope is left.

Can we use float in array?

Here is an image to show the sample run and output of the float array input output C language program. Here is the source code of the program to input 10 float elements in array and output them on screen. Here is a link to a related array program: Input and output of 10 element integer ( whole numbers ) array.

How to convert an array of strings to array of floats?

Let’s discuss a few ways to convert an array of strings to array of floats. Method #1 : Using astype import numpy as np ini_array = np.array (["1.1", "1.5", "2.7", "8.9"])

Is there a way to define an array float without size?

This is how stackoverflow works.! You have to specify the size if you are going to define array float in this way: You can define the array without the size. but it should be in this way: see the following topic for more details: How to initialize all members of an array to the same value?

What is the result of float X = 3544?

@DavidRF: The result of float x = 3.544; is the decimal numeral “3.544” converted to double and then converted again to float. For certain rare numerals, this double conversion produces a different result than converting a numeral suffixed with “f” directly to float.

How do I create an array with no static size?

float array [4]; array [0] = 3.544; array [1] = 5.544; array [2] = 6.544; array [3] = 6.544; This should work buddy. You can't create an array with no static size. You can create an array like this on the stack, which is mostly when you have smaller arrays: it is created in the scope and destroyed when that scope is left.


5 Answers

No, typecasting a struct to an array will not work. Compilers are allowed to add padding between members.

Arrays have no padding between members.

Note: there is nothing stopping you from casting, however, using value after cast results in undefined behavior.

like image 123
Thomas Matthews Avatar answered Oct 23 '22 23:10

Thomas Matthews


In a practical sense, yes you can do that and it will work in all the mostly used architectures and compilers.

See "Typical alignment of C structs on x86" section on Wikipedia.

More details:

  • floats are 4 bytes and no padding will be inserted (in practically all cases).

  • also most compilers have the option to specify the packing of structures and you can enforce that no padding is inserted( i.e. #pragma pack from visual studio )

  • arrays are guarantied to be contiguous in memory.

Can you guarantee that it will work in all CPUs in the world with all the compilers? No.. but I would definitely like to see a platform where this fails :)

EDIT: adding static_assert(sizeof(A) == 3*sizeof(float)) will make this code not compile if there are padding bytes. So then you'll be sure it works when it compiles.

like image 27
Sil Avatar answered Oct 23 '22 23:10

Sil


This is a strict aliasing violation, plain and simple. Any access with that pointer, to any element but the first, is undefined behavior in your case. And in more complex cases it's just plain undefined behavior regardless of which element you access.

If you need an array, use an array. std::array also has an overload for for std::get, so you can use that to name each individual array member:

using A = std::array<float, 3>;

enum AElement { X, Y, Z };

int main() {
  A a;
  get<X>(a) = 3.0f; // sets X;

  float* array = a.data(); // perfectly well defined
}
like image 19
StoryTeller - Unslander Monica Avatar answered Oct 24 '22 00:10

StoryTeller - Unslander Monica


For g++ you can use attribute for your struct, like this:

struct  A {
    float x;
    float y;
    float z;
}__attribute__((__packed__));

It's disable struct alignment.

like image 7
Pavel Avatar answered Oct 23 '22 23:10

Pavel


You can do that, until the compiler starts optimising, and then things go wrong.

Accessing any but the first element of a struct by using a pointer to the first element is undefined behaviour. "Undefined behaviour" means that anything can happen. The compiler may assume that there is no undefined behaviour.

There are many consequences that the compiler can deduce from that: If the compiler knows that your float* points to the first element of the struct, then it can deduce that every index to that array equals 0 (because anything else is undefined behaviour). If the compiler doesn't know this, then it can deduce that the array pointer cannot point to the struct, and changing array elements can't change struct elements and vice versa.

Can you see how this will go wrong?

like image 4
gnasher729 Avatar answered Oct 23 '22 23:10

gnasher729