Getting the int value from bytes

Programming, for all ages and all languages.
Post Reply
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Getting the int value from bytes

Post by piranha »

This may seem basic, but...

When you have an array of chars/bytes whatever, and you want to put them all into ints you do...

Code: Select all

int x = buf[10] | buf[11] | buf[12] <and so on...>
Right? Is this correct?

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

Personally, I prefer using the atoi() function.. :wink:
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Post by piranha »

This would be in my OS, so no standard functions...
This is specificaly for FS reading, in which the super-block's info for the number of blocks in the data area at offset 0x019C, length is 8 bytes....how to convert that into a long int...?
-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

piranha wrote:This would be in my OS, so no standard functions...
This is specificaly for FS reading, in which the super-block's info for the number of blocks in the data area at offset 0x019C, length is 8 bytes....how to convert that into a long int...?
-JL
Reorganize your data area so that the offset is a multiple of 8, and do:

long long result, *llp;

llp = (long long *) (data area + 0x0198); // after reorgainization
result = *llp;

Or, if you don't want to reorganize, then you are stuck with a dword boundary -- so do the same thing with longs, instead.

long long result;
unsigned long *lp;

lp = (long *) (data area + 0x019c);
result = (long long)*lp | (lp[1]<<32);
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

What's preventing you from reading this superblock into an allocated buffer?

Code: Select all

struct superblock {
        uint64_t length;
};
uint64_t sb_length_member;
struct superblock *sb = NULL;
sb = (struct superblock *)malloc(sizeof(struct superblock));
..int fd = open("/dev/something", O_RDONLY);
..lseek(fd, offset, ...);
..read(fd, sb, 8);
sb_length_member = sb->length;
Something along those lines would work... or so I'd assume... saves all the unnecessary conversion work.
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

Is the FS metadata big or little endian?

Is your OS platform big or little endian?

:twisted:
Every good solution is obvious once you've found it.
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Post by piranha »

what......?

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

Endianess. The order in which the individual bytes of an integer reside in memory.

x86 -> Little Endian.

PPC, Network -> Big Endian.

Your file system -> ??

Your platform -> ??
Every good solution is obvious once you've found it.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

The easy way - assuming same endianness of processor and data.
--no need, bewing did that for me. Incidentally, he quotes something which isn't in your post. Strange. Confused me for a while. I did wonder where he got that 0x19C malarky from...

Little endian processor with little endian data:

Code: Select all

uint32_t val = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
Big endian processor with little endian data:

Code: Select all

uint32_t val = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
Other two (little endian processor w/ big endian data, big endian processor w/ little endian data) - you work them out! :twisted:
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

Code: Select all

uint32_t val = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
(I hope the compiler is smart enough to reoptimize the 16 opcodes necessary for that. :wink: )

Really, as Brynet is almost suggesting -- the *smart* way to do all this is to redesign your whole superblock, so that every element of the thing is aligned on the proper "type" boundary -- then load it into memory, assign a structure pointer to it, and use it as a structure.
i= superblock -> numblks;

Then you don't have to worry about endianness, for the next few years, until your OS is complete enough that you start porting it to other types of CPUs. But shifting and ORing bytes together (as has been pointed out several times) is endian specific. So try not to do that, if you can avoid it.
Post Reply