1

This is my code:

#include <iostream>


//extract i:th bit from val of given addr with &
void extractBit(long long unsigned* ptr,int ith) {
    std::cout << (*ptr & (1LLU << ith) ? 1 : 0);
}


template <typename T> void printlnbits(T v)
{
    //v_size to hold the size of the generic variable
    const int v_size = sizeof(v) * 8;
    int j = 0;

    unsigned long long int* ptr = reinterpret_cast<unsigned long long int*>(&v);
        
    for (int n = v_size - 1; n >= 0; --n)
    {
        j++;
        extractBit(ptr, n);

        if (j == 8)
        {
            std::cout << " ";
            j = 0;
        }
    }
    std::cout << "\t" << v_size << std::endl;
}

struct foo {
    int a = 2;
    char b = -1;
    unsigned long long int x = 1LLU << 63;
};

int main() {
    const char a = 'a'; //97, displayed binary: 01100001, size:8bit
    const foo b; /*displayed binary: 00000000 00000000 00000000 00000000 00000000 000000000 00000000 00000000 11001100 11001100 11001100 11111111 00000000 00000000 00000000 00000010 
size: 128bit
*/

    printlnbits(a);
    printlnbits(b);
    return 0;
}

The char 'a' has the ascii value of 97 and is represented binary as: 01100001. And char has the size of 8bits.

The struct value is what i cannot comprehend. It is represented with the value: 14757395474574999554, or in binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11001100 11001100 11001100 11111111 00000000 00000000 00000000 00000010

and the struct has the size of 128bits. From what i understand is stored like this:

|----------------------------------------------|
| int a: 32bit | char b: 8bit | padding: 24bit-|
|----------------------------------------------|
|--------unsigned long long int x: 64bit-------|
|----------------------------------------------|

As you can see the struct is represented by a very odd binary number. Which method is used to store a struct of given variables in binary form? I have tried to find any IEEE standard for it without any success..

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • 4
    Your code has undefined behavior. You are not allowed to access the parts of a `foo` by casting it to a `long long*` – NathanOliver Sep 29 '21 at 13:09
  • It's not IEEE, it's ISO 14882 – Swift - Friday Pie Sep 29 '21 at 13:19
  • If you compile with `g++` or `clang++`, compile with `-g -fsanitize=address,undefined` and you'll see [something like this](https://godbolt.org/z/eTTP6Eb8P) - that usually helps – Ted Lyngmo Sep 29 '21 at 13:29
  • You never advance `ptr`, so you keep shifting the same value. – molbdnilo Sep 29 '21 at 13:29
  • The first 64 bits are the initial 64 bits of your struct - `a`, `b`, and padding - shifted too far to the left (which is formally undefined, but apparently produces zero in this particular case). The next 24 bits is the padding. Then you have `b` (`11111111`) and `a` (`0000...0010`). – molbdnilo Sep 29 '21 at 13:58

1 Answers1

0

The value of last 8 bytes is actually right one, including padding. But you print structure backward,

for (int n = v_size - 1; n >= 0; --n)

so value of a is last 4 bytes backward. Only individual fields are subject of byte order in case of little endian, bitwise shift operation is endianness-agnostic so you see proper byte values.

Also you never go past first 64 bit, because ptr value doesn't change. Should be something like

extractBit(ptr + n /  8*sizeof(long long int), n %  8*sizeof(long long int) );

As Nathan mentioned in comment your mode of access formally results in undefined behaviour.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42