You can always treat any object variable as a sequence of bytes. For this very purpose, it is explicitly allowed (and does not violate aliasing or constitute type punning) to reinterpret any object pointer as a pointer to the first element in an array of bytes (i.e. any char
type).
Example:
T x;
char const * p = reinterpret_cast<char const *>(&x);
for (std::size_t i = 0; i != sizeof x; ++i) { /* p[i] is the ith byte in x */ }
For your case:
float data[N];
char const * p = reinterpret_cast<char const *>(data);
write(fd, p, sizeof data);