how to cast an array of char into a single integer number?
Solution 1
You cast (char*) to (int). What you should do is cast to pointer to integer, i.e.
t_num = *((int*) s_num));
But really you should extract your code into it's own function and make sure that:
- endianness is correct
sizeof(int) == 4
- Use C++ casts (i.e.
static, dynamic, const, reinterpret
)
Solution 2
Assuming a little-endian machine with a 32-bit integer, you can do:
char s_num[4] = {0xAF, 0x50, 0x28, 0x1};
int t_num = *((int*)s_num);
To break it into steps:
-
s_num
is an array, which can be interpreted as a pointer to its first element (char*
here) - Cast
s_num
toint*
because of (1) - it's OK to cast pointers - Access the integer pointed to by the cast pointer (dereference)
To have 0xAF
as the low byte of the integer. Fuller example (C code):
#include <stdio.h>
int main()
{
char s_num[4] = {0xAF, 0x50, 0x28, 0x1};
int t_num = *((int*)s_num);
printf("%x\n", t_num);
return 0;
}
Prints:
12850af
As expected.
Note that this method isn't too portable, as it assumes endianness and integer size. If you have a simple task to perform on a single machine you may get away with it, but for something production quality you'll have to take portability into account.
Also, in C++ code it would be better to use reinterpret_cast
instead of the C-style cast.
Solution 3
I find using the std bitset the most explicit way of doing conversions (In particular debugging.)
The following perhaps is not what you want in your final code (too verbose maybe) - but I find it great for trying to understand exactly what is going on.
http://www.cplusplus.com/reference/stl/bitset/
#include <bitset>
#include <iostream>
#include <string>
int
main (int ac, char **av)
{
char s_num[4] = {120, 80, 40, 1};
std::bitset<8> zeroth = s_num[0];
std::bitset<8> first = s_num[1];
std::bitset<8> second = s_num[2];
std::bitset<8> third = s_num[3];
std::bitset<32> combo;
for(size_t i=0;i<8;++i){
combo[i] = zeroth[i];
combo[i+8] = first[i];
combo[i+16] = second[i];
combo[i+24] = third[i];
}
for(size_t i = 0; i<32; ++i)
{
std::cout<<"bits ["<<i<<"] ="<<combo.test(i)<<std::endl;
}
std::cout<<"int = "<<combo.to_ulong()<<std::endl;
}
Solution 4
Axel's answer violates the strict aliasing rule, at least since C++14. So I post this answer for future users.
Apart from endianness and size issues, a safe way is to use std::memcpy
, i.e.
unsigned char s_num[4] = {13, 0, 0, 0};
// ^^^^^^^^ // ^^ fix endianness issue
// use unsigned char to avoid potential issues caused by sign bit
int t_num;
std::memcpy(&t_num, s_num, 4);
sepisoad
My name is "Sepehr Aryani" and I'm A full-stack develper. I've been working professionally as a software engineer since 2010. My major area of interest is designing and developing services and web apps. I am proficient at C++/Go/Python/Javascript(React/Redux)
Updated on July 22, 2022Comments
-
sepisoad almost 2 years
i'm trying to read contents of PNG file.
As you may know, all data is written in a 4-byte manner in png files, both text and numbers. so if we have number 35234 it is save in this way: [1000][1001][1010][0010].
but sometimes numbers are shorter, so the first bytes are zero, and when I read the array and cast it from char* to integer I get wrong number. for example [0000] [0000] [0001] [1011] sometimes numbers are misinterpreted as negative numbers and simetimes as zero!
let me give you an intuitive example:
char s_num[4] = {120, 80, 40, 1}; int t_num = 0; t_num = int(s_num);
I wish I could explain my problem well!
how can i cast such arrays into a single integer value?
ok ok ok, let me change my code to explain it better:
char s_num[4] = {0, 0, 0, 13}; int t_num; t_num = *((int*) s_num); cout << "t_num: " << t_num << endl;
here we have to get 13 as the result, ok? but again with this new solution the answer is wrong, you can test on your computers! i get this number:218103808 which is definitely wrong!
-
Eli Bendersky over 13 yearsWhat machine do you have that overflows an int on 32767?
-
Philip Potter over 13 yearsnot necessarily so. Many C++ implementations have 32-bit or even 64-bit
int
which won't overflow after 32767. -
Eli Bendersky over 13 years@Philip: "Many..." is putting it mildly. It would be challenging to find one where it's smaller than 32 bits these days, outside of the embedded domain of course.
-
Eli Bendersky over 13 yearsI'm not sure this is what he's asking
-
Philip Potter over 13 years@Eli i don't think he's sure what he's asking. But this is the result that his example asks for.
-
jamesmortensen over 13 yearsI stand corrected. I must have been dyslexic and looking at the wrong data type. With that said, do we need to remove this answer?
-
Axel over 13 yearshaha, so there's someone still stuck on a 16-bit compiler. embedded system?
-
sepisoad over 13 yearsthe same happend when I used your solution
-
Axel over 13 yearswhat does same results mean? perhaps you should explain, why you expect this to give 241...
-
Axel over 13 yearsOh... what you want is just to sum up the byte values of your 4 characters. That would give 241. Macieks' answer does that. But is that really what you want to do? Looks strange to me (not the code, I'm trying to understand your problem).
-
AndyG over 7 years@iammilind: Did you read the entirety of the answer you linked?
char*
is one of the few occasions where this doesn't break aliasing -
AndyG over 7 years@iammilind: To back up my statement, refer to the C++ standard
§3.10/10 Lvalues and rvalues [basic.lval]
Which makes special provisions forchar
andunsigned char
-
xskxzr over 6 years
-
Summer Sun almost 6 yearscould you explain why is it of reverse order, I think it should be af50281?
-
Summer Sun almost 6 yearsThank you Eli, I got it now.