Casting Char[4] into int*

C

Chlikaflok

See, I have this code, I'm trying to open and run a MIDI file, and I'm
parsing the header to check it's integrity :

// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;

length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) )
{Error msgs and stuff}

SINT32 is a typedef for signed int

Using a perfectly good midi file, this segment of code should go right
past the IF block, because the buffer char array should contain ([0],
[0],[0],[6]), which it does. But when I evaluate the length expression
in the IF clause, the value is exactly and always : 100663296.

As I understand it, the 4-byte char array contains "00000006", which
when cast to int should read "6", correct me if I'm wrong. Using
buffer[3]instead of the *length evaluation in the IF resolves the
problem, but that way of using the buffer data is used all over the
library I'm using and I believe it was done that way for a reason.

Any help would be welcome,
Thx in advance for at least reading this,
Chlikaflok.
 
P

p.lepin

// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;

length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) )
{Error msgs and stuff}

SINT32 is a typedef for signed int

Using a perfectly good midi file, this segment of code
should go right past the IF block, because the buffer
char array should contain ([0], [0],[0],[6]), which it
does. But when I evaluate the length expression in the IF
clause, the value is exactly and always : 100663296.

As I understand it, the 4-byte char array contains
"00000006", which when cast to int should read "6",
correct me if I'm wrong.

I believe you are wrong. That depends on the endianness of
your platform. Assuming your char is 8-bit long, and the
last char being most significant, the result of this
conversion should be 6 * ( 2 ^ 24 ) = 100663296, which is
precisely what you're getting.

Anyway, I'm not sure this is even topical in this group;
you would probably get more help in a platform-specific
group for your platform.
 
C

Chlikaflok

// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;
length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) )
{Error msgs and stuff}
SINT32 is a typedef for signed int
Using a perfectly good midi file, this segment of code
should go right past the IF block, because the buffer
char array should contain ([0], [0],[0],[6]), which it
does. But when I evaluate the length expression in the IF
clause, the value is exactly and always : 100663296.
As I understand it, the 4-byte char array contains
"00000006", which when cast to int should read "6",
correct me if I'm wrong.

I believe you are wrong. That depends on the endianness of
your platform. Assuming your char is 8-bit long, and the
last char being most significant, the result of this
conversion should be 6 * ( 2 ^ 24 ) = 100663296, which is
precisely what you're getting.

Anyway, I'm not sure this is even topical in this group;
you would probably get more help in a platform-specific
group for your platform.

Wow! Thank you, it now works, you were right, I had seen the
endianness algorithms in my code, but it didn't occur to me that I had
forgotten to define the endianness in my precompiler.

And sorry for not having posted in the right group, but up until your
answer I wasn't aware that the error was platform-specifications
oriented, so I couldn't post in the right group, so I chose to go to
the most appropriate : the c++ group for c++ problems, no?

Anyway, I'll try to be more wary of the topicality of my questions in
the future, and thanks again!

Cheers,
Chlikaflok.
 
V

Victor Bazarov

See, I have this code, I'm trying to open and run a MIDI file, and I'm
parsing the header to check it's integrity :

// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;

length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) )
{Error msgs and stuff}

SINT32 is a typedef for signed int

Using a perfectly good midi file, this segment of code should go right
past the IF block, because the buffer char array should contain ([0],
[0],[0],[6]), which it does. But when I evaluate the length expression
in the IF clause, the value is exactly and always : 100663296.

As I understand it, the 4-byte char array contains "00000006", which
when cast to int should read "6", correct me if I'm wrong. Using
buffer[3]instead of the *length evaluation in the IF resolves the
problem, but that way of using the buffer data is used all over the
library I'm using and I believe it was done that way for a reason.

Could it be you're running into the endianness conflict here?

100663296 is 0x06000000, i.e. 6 shifted left 24 positions. What you
need is to rearrange the bytes after reading them before casting them
to your 'SINT32', or simply make your SINT32 out of the bytes you got
using shift and OR. It is a common problem with reading files designed
to be read on different platforms.

V
 
V

Victor Bazarov

// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;
length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) )
{Error msgs and stuff}
SINT32 is a typedef for signed int
[..]

Anyway, I'm not sure this is even topical in this group;
you would probably get more help in a platform-specific
group for your platform.
[..]

And sorry for not having posted in the right group, but up until your
answer I wasn't aware that the error was platform-specifications
oriented, so I couldn't post in the right group, so I chose to go to
the most appropriate : the c++ group for c++ problems, no?

You have posted in the right newsgroup, don't worry about it.

V
 
J

James Kanze

See, I have this code, I'm trying to open and run a MIDI file, and I'm
parsing the header to check it's integrity :
// Parse header info.
char chunkType[4];
char buffer[4];
SINT32 *length;
if ( !file_.read( chunkType, 4 ) ) goto error;
if ( !file_.read( buffer, 4 ) ) goto error;
length = (SINT32 *) &buffer;
if ( strncmp( chunkType, "MThd", 4 ) || ( *length != 6 ) )
{Error msgs and stuff}
SINT32 is a typedef for signed int

Which may be larger than 4 bytes, in which case, you have a real
problem.
Using a perfectly good midi file, this segment of code should go right
past the IF block, because the buffer char array should contain ([0],
[0],[0],[6]), which it does. But when I evaluate the length expression
in the IF clause, the value is exactly and always : 100663296.

And on other platforms, it may give 0, or 393216, or even cause
a crash.
As I understand it, the 4-byte char array contains "00000006", which
when cast to int should read "6", correct me if I'm wrong.

You're wrong. It's completely undefined behavior. Even if your
platform uses four byte integers, it depends on the byte order:
I've seen at least three different arrangements in my own
experience (which would result in 6, 393216 or 100663296).
Using
buffer[3]instead of the *length evaluation in the IF resolves the
problem, but that way of using the buffer data is used all over the
library I'm using and I believe it was done that way for a reason.

Maybe the reason was that the author didn't know C or C++. Or
had a tormented way of thinking. If I want to verify that four
bytes contain, successively, 0, 0, 0 and 6, I'll do just that.
Say with:

static char const ref[ 4 ] = { 0, 0, 0, 6 } ;
if ( memcmp( ref, length, 4 ) != 0 ) {
// error...
}

or (more likely in new code):
static char const ref[ 4 ] = { 0, 0, 0, 6 } ;
if ( ! std::equal( begin( ref ), end( ref ), length ) ) {
// error...
}

In your case, I'd probably work on the whole 8 byte chunk in one
go, comparing with a reference:
static char const ref[ 8 ] = { 'M', 'T', 'h', 'd', 0, 0, 0,
6 } ;
I might even use the numerical values for the characters, since
what I'm looking for is a specific content, regardless of the
code set I use in my own program.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top