Click here to Skip to main content
13,053,399 members (62,125 online)
Rate this:
 
Please Sign up or sign in to vote.
See more:
Dear all,

I think it is simple program. But I really face problem and tired out of finding solution. So, I really need your help.

Here is the problem.
I saved 7E FF FF FF FF FF FF 7E (8 bytes) data in binary file.
I would like to retrieve it as reverse order with binary file.

The following is output function.
void outputint64(int i) {
	__int64 app1 = (__int64)mem[i+3] << 48; //mem is short type array data read from binary file
	__int64 app2 = (__int64)mem[i+2] << 32;
	__int64 app3 = (__int64)mem[i+1] << 16;
	__int64 app4 = (__int64)mem[i];
	__int64 app = (__int64)app1 | (__int64)app2 | (__int64)app3 | (__int64)app4;
	printf("int64 value is : %I64x", app);
}


app1 output is 0x 7E FF 00 00 00 00 00 00 //the output is as I expect
app2 output is 0x FF FF FF FF 00 00 00 00 //actually I only expect 0x 00 00 FF FF 00 00 00 00
app3 output is 0x FF FF FF FF FF FF 00 00 //actually I only expect 0x 00 00 00 00 FF FF 00 00
app4 output is 0x FF FF FF FF FF FF FF 7E //actually I only expect 0x 00 00 00 00 00 00 FF 7E

So, app output becomes 0x FF FF FF FF FF FF FF 7E, even though I expect as 0x 7E FF FF FF FF FF FF 7E.

How should I modify to get the expected result?
If you have any idea, please help me.

Thanks in advance.
Posted 10-Oct-12 5:49am
Updated 10-Oct-12 6:07am
DaveAuld193.2K
v4
Comments
enhzflep 10-Oct-12 12:07pm
   
What's stored in 'mem[]'?
Could you provide a small, but complete sample program?

EDIT: Never-mind - just read the comment. :oops:
April2004 10-Oct-12 12:11pm
   
Hi,
Here is my simple source code. I just cut out the points of my current problem.Thanks for your help.

#include <stdio.h>
#include <conio.h>
#include <string.h>

void outputshort(int i);
void outputint64(int i);

short mem[100];

void main(){
FILE* fp = 0;

short x[100];

char *filename = "C:\\chk\\test.dat";
fp = fopen(filename, "wb");
if (fp) {
for (int j = 0; j < 10; j++){
x[j] = (short)j;
fwrite(&x[j], 1, sizeof(x[j]), fp);
}
__int64 val = 9151314442816847742; //7E FF FF FF FF FF FF 7E
fwrite(&val, 1, sizeof(val), fp);
for (int j = 10; j < 20; j++){
x[j] = (short)j;
fwrite(&x[j], 1, sizeof(x[j]), fp);
}
__int64 val1 = 9114441220867751806; //7E 7C FF FF FF FF FF 7E
fwrite(&val1, 1, sizeof(val1), fp);
}

fclose(fp);

FILE* fr = fopen(filename, "r");
if (fr) {
fread(&mem, sizeof(mem), 1, fr);
}

outputshort(9);
outputint64(10);

_getch();
}

void outputshort(int i) {
printf("short value is : %d\n", mem[i]);
}

void outputint64(int i) {
__int64 app1 = (__int64)mem[i+3] << 48;
__int64 app2 = (__int64)mem[i+2] << 32;
__int64 app3 = (__int64)mem[i+1] << 16;
__int64 app4 = (__int64)mem[i];
__int64 app = (__int64)app1 | (__int64)app2 | (__int64)app3 | (__int64)app4;
printf("int64 value is : %I64x", app);
}

Best Regards
Jochen Arndt 10-Oct-12 12:21pm
   
If you use Visual C++, you can use the _byteswap_uint64() function.
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 1

I think you'll find that the problem is one of sign-extension, that is to say - if you've only declared mem to be an array of 4 shorts, they are SIGNEDshorts. App1 works ok because the first short is 0x7E - or 0111 1110

The others fail, because they all begin with a 1 bit in the MSB (most significant bit) This means they are interpreted as signed (-ve, in fact), so to maintain that negativity when they are multiplied 0 which is what a left shift is, they have 1 bits inserted (in the more significat bits), rather than 0 bits - which are still added in the least significant bits.

To fix, declare mem as an array of UNsigned shorts. (This behaviour doesn't happen in ASM - it's the C compiler does it for (to?) you)

The following code produces the output:

int64 value is : 7effffffffffff7e



#include <stdio.h>
#include <stdlib.h>
 
unsigned short mem[4];
 
void outputint64(__int64 i)
{
    __int64 app1 = (__int64)mem[i+3] << 48; //mem is short type array data read from binary file
    __int64 app2 = (__int64)mem[i+2] << 32;
    __int64 app3 = (__int64)mem[i+1] << 16;
    __int64 app4 = (__int64)mem[i];
    __int64 app = (__int64)app1 | (__int64)app2 | (__int64)app3 | (__int64)app4;
    printf("int64 value is : %I64x", app);
}
 
int main()
{
    FILE *fp;
    fp = fopen("inputData.bin", "rb");
    fread(mem, 2, 4, fp);
    fclose(fp);
    int offset = 0;
 
    outputint64(offset);
}
  Permalink  
v2
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 2

short is a signed type. So, when you cast from short to __int64, it fills the additional bytes according to the sign bit. In your case it's 1 (when the value of the high byte is FF). So the additional bytes are filled with FF's.


You can fix that issue, by adding an additional & operation for each << operation. Something like:


__int64 app3 = ((__int64)mem[i+1] & (__int64)0xffff) << 16;

Or, by adding an additional cast to unsigned short. Something like:


__int64 app3 = (__int64)(unsigned short)mem[i+1] << 16;

By the way, you can set the value for the app variable (in the outputint64 function), in one line only:


__int64 app = *((__int64*)&mem[i]);

:)
  Permalink  
v6
Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 3

Dear enhzflep, Jochen Arndt and Shmuel Zang,

Thank you very much for your advice.
Because of your help, I can finish my job.
I used unsigned short as you said. The work is done well.

I will also practice _byteswap_uint64(), *((__int64*)&mem[i] for improving my programming knowledge.

Thanks a lot for your helps
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


Advertise | Privacy | Mobile
Web02 | 2.8.170713.1 | Last Updated 11 Oct 2012
Copyright © CodeProject, 1999-2017
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100