0

I'm receiving 8 groups of 4 chars which represent 8 floats, but I'm struggling with C++ to reassemble them.

Edited to express the idea (this code is obviously wrong) :

// Re-assembly of 32 bytes into 8 float
float concat_value[8];
for (int i = 0; i < 8; i ++) {
concat_value[i] = buffer[4 * i + 3];
concat_value[i] = concat_value[i] << 8;
concat_value[i] = (concat_value[i] & buffer[4 * i + 2]);
concat_value[i] = concat_value[i] << 8;
concat_value[i] = (concat_value[i] & buffer[4 * i + 1]);
concat_value[i] = concat_value[i] << 8;
concat_value[i] = (concat_value[i] & buffer[4 * i + 0]);
std::cout << "   concat_value: " << concat_value[i] << std::endl;
}

I'm sorry I know it still won't work, it just represents the idea.

If you can light me up.

Thanks a lot,

Jean-François

  • 1
    "Represent 8 floats" how exactly? – melpomene Dec 03 '17 at 20:05
  • An assignment nullifies the effect of all previous assignments to the same object, so this entire loop body is equivalent to `concat_value[i] = (concat_value[i] & buffer[4 * i + 9 + 0]);`. – n. m. could be an AI Dec 03 '17 at 20:13
  • A few questions: Is the type of `buffer` `unsigned char[]` or `int[]`? You are assigning your buffer directly to `concat_value`, which is `int[]`. `unsigned char[] is the equivalent of byte in c++. What's the extra + 9 for? Is your data offset somehow? The code you're using doesn't read any data from buffer indices 0-8. – Kilves Dec 03 '17 at 20:14
  • `&` removes data, it doesn't add it. – melpomene Dec 03 '17 at 20:17
  • You can probably just `memcpy` from the buffer to the float, but it depends on the exact representation and endianess. – interjay Dec 03 '17 at 20:19
  • @melpomene True, my mistake. He indeed should use `|` instead of `&` – Kilves Dec 03 '17 at 20:22
  • I'm sorry I should have removed the offset.From unsigned char[] – Jean-Francois Simon Dec 03 '17 at 20:22
  • Correction using bitwite OR ( | ). But the results are not correct anyway after the reassembly. – Jean-Francois Simon Dec 03 '17 at 20:37
  • @Jean-FrancoisSimon Your code has confused poeple who have not read you text, it is becoming more and more a pathological behavior on stack overflow. The exact duplicate is just not a duplicate, what you want is just convert an object representation, in a buffer of unsigned char to its actual type. `reinterpret_cast` is just made for that!! – Oliv Dec 03 '17 at 21:33
  • If the duplicate doesn't answer your question, you will need to explain how the "group of 4 chars" representing a float was initially formed. (Because the answer to this question is to do the reverse of that procedure) – M.M Dec 03 '17 at 21:49
  • @M.M. come on M.M. He just has a buffer holding the representation of floats, just forget its code. Just read my answer, it worked, he just say it. It is just a trivial question: "how to get back a pointer to object from a pointer to its representation ?" – Oliv Dec 03 '17 at 21:56
  • @Oliv your code causes undefined behaviour if `buffer` is actually an array of unsigned char (which OP doesn't specify) . I downvote answers that recommend undefined behaviour even if it appears to work for now. (The comments to your answer already explain why it is undefined behaviour) – M.M Dec 03 '17 at 22:20
  • @M.M. It is not undefined behavior, I have no idea why you authorize yourself to such wrong pontifications. But your are really wrong. You probably have overlooked the part of the standard where an object is said to occupy a region of storage. Read [this bit_cast proposal](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0476r2.html), then also check this [code](https://github.com/jfbastien/bit_cast/blob/master/bit_cast.h). This is the second review by the c++ commitee, so they have certainly not missed an UB! – Oliv Dec 04 '17 at 09:23
  • @M.M. Honestly, I think that the fact there are so much confusion about c++ memory/object model is the "de facto" proof that at least the related part of this specification are poorly written, or at worst, an error in the design of C and C++ languages. Unfortunatly, written text tend after few years, to generate some kind of stupid veneration, we forget texts have been written and idea conceived by fallible men, as we all are. – Oliv Dec 04 '17 at 09:34

1 Answers1

-3

In your text, you say that you have in buffer the binary representation of 8 floats. But your code is realy far from doing this.

According to your code, it seems that the buffer is a little endian representation of a float, so I'll suppose you are compiling on a x86. So if these suppositions are right this code shall work:

float concat_value[8];
for (int i = 0; i < 8; i ++) {
    concat_value[i] = *reinterpret_cast<float*>(buffer+i*sizeof(float));
    std::cout << "   concat_value: " << concat_value[i] << std::endl;
}

if your aim was to just keep in concat_value the integral part of the floats then:

int concat_value[8];
for (int i = 0; i < 8; i ++) {
    float v = *reinterpret_cast<float*>(buffer+i*sizeof(float));
    std::cout << "   concat_value: " << v << std::endl;
    concat_value[i]=v;
}
Oliv
  • 17,610
  • 1
  • 29
  • 72
  • 1
    This is a violation of the strict aliasing rule. It's better to `memcpy` instead. – interjay Dec 03 '17 at 20:53
  • 2
    This can fail if `buffer` is not properly aligned for objects of type `float`. `memcpy(&concat_value[i], buffer + i*sizeof(float))` is better and respects C++ semantics regarding converting pointers and accessing objects through pointers of other types. – Eric Postpischil Dec 03 '17 at 20:53
  • @interjay, it is not a violation of strict aliasing rule, because there is no two lvalue with different type pointing to a same memory location. Honestly it surprised me the first time I saw it, their is an accepted proposal in c++20 called bit_cast that just do that. – Oliv Dec 03 '17 at 20:57
  • @EricPostpischil actualy, mis alignment is supported on x86, this is one of my hypothesis. – Oliv Dec 03 '17 at 21:00
  • @Oliv There are two types (otherwise you wouldn't need to cast): a `char` array and a `float`. – interjay Dec 03 '17 at 21:01
  • @Oliv: The OP did not say they were running in x86, nor which C++ implementation. x86 does have alignment exceptions, depending on how floating-point loads and stores are implemented. Regardless of alignment issues, aliasing types in ways unsupported by the language may have unpredictable effects, largely due to transformations performed by modern optimizers. – Eric Postpischil Dec 03 '17 at 21:03
  • Thanks Oliv, that works perfectly. I'll dig into this issue when I have more time so as to do this conversion more stricly. – Jean-Francois Simon Dec 03 '17 at 21:04
  • @interjay, hopefully buffer is just that! – Oliv Dec 03 '17 at 21:05
  • `buffer` is presumably a `char` array, which you are not allowed to access as a `float`. – interjay Dec 03 '17 at 21:05
  • @EricPostpischil Honestly, I just made bet, It would have me surprised if such a question was asked by a professional targeting an embedded device!! – Oliv Dec 03 '17 at 21:10
  • @EricPostpischil You interesting me about mis alignment exception, actualy I just have read (today realy) the amd prommer's guide but I have still not read the part about x87. Have you just a reference for what you assert? – Oliv Dec 03 '17 at 21:12
  • @interjay, If buffer is the representation of an array of float, there is just no problem: an object occupies a region of storage, storage which is a sequence of char. – Oliv Dec 03 '17 at 21:15
  • @Jean-FrancoisSimon There are just no issues, just check buffer is a pointer to unsigned char. Actualy if you dig, you will discover that c++ object model is under specified! But if you want to dig, I think the following c++ standard section "must be known by heart (par coeur)": [intro.memory] [intro.object] [basic.lifetime] [basic.types], then for this question [expr.static.cast] [expr.reinterpret.cast]. – Oliv Dec 03 '17 at 21:26
  • @Oliv: Regarding alignment: The relevant manual is [Intel 64 and IA-32 Architectures Software Developer’s Manual](https://software.intel.com/en-us/articles/intel-sdm). Some relevant aspects include the alignment check flag (AC), which may be set on older processors to require alignment and the SSE and AVX instructions such as `movaps`, which a compiler may use on newer processors to move floating-point data (especially if you are doing four or eight at a time, and the compiler supports vectorization). – Eric Postpischil Dec 03 '17 at 21:39
  • 1
    @Oliv: Regarding type aliasing: The C++ standard requires that programs follow the rules about accessing objects through proper types of pointers in order to enable C++ implementations to optimize. For example, if a routine is passed an `int *A` and `float *B`, the compiler is allowed to deduce that no changes to anything pointed to by A will cause any changes in anything pointed to by B, because they are different types. When optimizing, this allows the compiler to cache values from B in registers instead of reloading them from memory. If you violate the rules, this optimization will break. – Eric Postpischil Dec 03 '17 at 21:43
  • @EricPostpischil Thank you! I have not read the part about SIMD too! I thought I could just skip it! I was wrong, I ll read it entirely tomorow so! – Oliv Dec 03 '17 at 21:43
  • @EricPostpischil But this is a `buffer` of `unsigned char`!! I don't know why he converted the buffer to int then to float. The mark for duplicate is erroneous. What he wanted is just to get back a pointer to float from a buffer (unsigned char) holding the representation of a float. This is what he has written in the text! Unfortunately, its code is so weared it has confused many poeple, at least those who put the duplicate mark. – Oliv Dec 03 '17 at 21:46
  • And the best is that I continue to get downvoted by guys who don't read the questions!!! – Oliv Dec 03 '17 at 21:49
  • 1
    The type of `buffer`'s elements is `char`, so the standard says that you are not allowed to access them as `float`, but only as some variation of `char`. The fact that it happens to hold a valid representation of a float does not help. And you are getting downvoted not because people haven't read the question, but because your answer is wrong. – interjay Dec 03 '17 at 22:14
  • Of course I'm far from professional, but I love C++ and learning a lot. So many things to understand, one + year at serious learning not much. – Jean-Francois Simon Dec 04 '17 at 20:51
  • @Jean-FrancoisSimon Bien je peux te parler en français j'imagine, je suis fatigué te tout le temps devoir travailler en anglais! J'ai suivi un chemin similaire dans le domaine de la programmation. J'ai perdu bcp de temps à lire des sources inutiles. Du coup je vais partager avec toi mon expérience d'apprenant. Le meilleur boucain pour le c++ est Stroustrup "the c++ programming language". Ensuite je pense que la doc "amd programmer's manual" permet de comprendre comment fonction une machine moderne, et pour comprendre un os, je te conseille "the linux programming interface". – Oliv Dec 04 '17 at 21:15
  • Enfin je pense qu'il faut que tu lises au moins 2 fois les 500 premières pages du standard et que tu prennes l'habitude de t'y référer. C'est vraiment la source la plus claire que je connaisse. – Oliv Dec 04 '17 at 21:17