#Casting int to unsigned char[4]

77 messages · Page 1 of 1 (latest)

final cove
#

I need to convert an int to an array of four unsigned char. How can I do this in C++?

I am a fresh beginner in C++ (3 days of active coding with prior experience in python) and know this is probably primitive, but I can't seem to figure it out.

still pivotBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

velvet kite
#

unsigned char uc_num1 = (unsigned char) num1;
perhaps?

rose tapir
rose tapir
final cove
#

I am reading an existing file where some data is being stored as a single int but is actually four chars encoded into a single int. For example 33752065 is actually char{2,3,4,1}

#

in this case 00000010000000110000010000000001b = 33752065 but it should be read as 00000010b 00000011b 00000100b 00000001b = 2 3 4 1

pseudo vale
rose tapir
#

that's what I was about to suggest

#

I would toss in a static_assert(sizeof(int) == 4) to be safe to make sure you validate your assumption

#

or use std::int32_t I guess instead of int

vestal pond
#

but do this ONLY if charArray size is always a multiple of 4! Else it can result in a bad behavior.

vestal pond
#

why not

rose tapir
#

because it's UB

#

type punning

vestal pond
#

and? it works

#

i mean it would be more safe to use int32_t instead of int, but else

rose tapir
#

until it doesn't, obviously, because it's UB

vestal pond
#

what should UB be?

rose tapir
#

int* intPointer = reinterpret_cast<int*>(&charArray[0]);

vestal pond
#

idk what UB means so idk

rose tapir
#

undefined behavior

vestal pond
#

how so

scarlet zenith
#

tl;dr stuff that's not allowed by the language

vestal pond
#

char[] is an array

scarlet zenith
#

the stuff you posted is as allowed as dividing by zero

#

or indexing out of bounds

#

type punning (the thing you posted) violates strict aliasing rules, and generally isn't allowed by the language, whereas memcpy is an allowed construct and in the simple cases it will compile down to what you tried to write

vestal pond
#

okay again what isn't allowed there? Like which computer rule it violates?

scarlet zenith
#

it's a language rule

#

meaning the compiler, since it assumes you respect language rules, may emit invalid "instructions"

#

or "instructions" that doesn't behave the way you would expect it to behave

vestal pond
#

you have literally an index to the first bit of char[4]
an array is internal constructed at begin with the type and then with the concret bits of the array, no waste informations.
so if you point to the first char and reinterpret the information, then you can call the informations of 4x8 bits (int), instead of 1x8 bits (char) ... how is that "bad"?

scarlet zenith
#

I literally just told you, it's strict aliasing rules

vestal pond
#

then why the hell reinterpret_cast exists?

scarlet zenith
vestal pond
#

no but thats how binary work

#

in fact its a bit more complex but thats simplified

scarlet zenith
# vestal pond then why the hell reinterpret_cast exists?

for other cases, and those are rare and few cases where they come up, which is part of why generally speaking if you need reinterpret_cast it often means you're doing something wrong, or have to deal with something someone else did wrong
or there are no other better constructs available so you willingly decide to eat the UB but if you do that normally you throw a bunch of tests and coverage at it to make as sure as possible that you detect any breakage as early as possible

scarlet zenith
#

the language has rules, rules that you have to follow

#

indexing out of bounds is UB by language design, and the consequence of it are varied at runtime

#

even just looking at the "binary"

vestal pond
lost field
#

this is like calling sizeof on a pointer...
It sometimes works, ofc. If your data is the same size as a pointer is...

scarlet zenith
# vestal pond no but thats how the stuff is stored

and the code that accesses whatever is "stored" is produced by the compiler, which is free to not at all access anything if by language rules or any optmization it assess that that shouldn't be necessary, invalidating any mental model you had to would rely on "accessing/reading" the memory

#

and even if everything happened to work well, if it's fobidden by the language it is forbidden by the language

#

and this kind of "type punning" is not uncommon to encounter in the wild, but if you have other options then the general recommendation is to just use the other option

lost field
#

yep, if you can do it it doesn't mean you should

scarlet zenith
#

because this specific kind of "type punning" doesn't have great alternatives, except that in OP's case it has

#

it's memcpy

#

and if you want a poster child, short, simplified to the point of being stupid, example of a compiler doing an optimization that produces "nonsense"

vestal pond
lost field
#

wait op just wants to convert an int into a char array?

scarlet zenith
#

;compile -O2

#include <iostream>

int foo( float *f, int *i ) { 
    *i = 1;               
    *f = 0.f;            
   
   return *i;
}

int main() {
    int x = 0;
    
    std::cout << x << "\n";   // Expect 0
    x = foo(reinterpret_cast<float*>(&x), &x);
    std::cout << x << "\n";   // Expect 0?
}
vestal pond
#

yes

viscid boneBOT
#
Program Output
0
1
scarlet zenith
vestal pond
#

wtf is memcpy

lost field
#

by that do we man we want to convert 1234 to ['1' , '2' , '3' , '4'] ?

lost field
scarlet zenith
#

they want the actual bytes

lost field
#

well then, memcpy

still pivotBOT
lost field
#

copies memory from one adress to another basically...

scarlet zenith
#

;compile

#include <iostream>
#include <cstring>
int main() {
  int i = 33752065;
  unsigned char ac[sizeof(int)];
  std::memcpy(ac, &i, sizeof(int));
  for (auto const c : ac)
    std::cout << static_cast<int>(c) << ' ';
}
viscid boneBOT
#
Program Output
1 4 3 2
scarlet zenith
#

right, there's also the question of endianness

#

oh well

lost field
#

I forgot we are doing cpp as soon as memcpy was mentioned haha, at least we have foreach

random cove
random cove