[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::c_plus_plus

Title:C++
Notice:Read 1.* and use keywords (e.g. SHOW KEY/FULL KIT_CXX_VAX_VMS)
Moderator:DECCXX::AMARTIN
Created:Fri Nov 06 1987
Last Modified:Thu Jun 05 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3604
Total number of notes:18242

3541.0. "recast int to long int?" by GIDDAY::STRAUSS (talking through my binoculars) Fri Apr 18 1997 04:48

    A question about whether the C++ compiler recasts int to long int.
    
    This code fragment comes from a customer's program compiled and run on
    UNIX V3.2C ...
    
    	int p1, p2, len;
    	p1 = litPointers[6] * 256 + litPointers[7];
    		:
    	fseek(LitFV, 2048 + p1, 0);
    
    As you see, p1 is declared as "int".
    However, the fseek(3) man page says that the offset should be "long int" ...
    
      int fseek(
              FILE *stream,
              long int offset,     <---
              int whence);
    
    The customer states ...
         "The compiler should cast the int values successfully to long int
         in the second parameter of fseek."
    
    Is he correct?
    I would disagree, but as I don't know C++ I'd appreciate an
    authoritative answer.
    
    Thanks in advance for any comments.
    
    	leon (C++ newbie)
T.RTitleUserPersonal
Name
DateLines
3541.1Briefly, customer is right.WIBBIN::NOYCEPulling weeds, pickin' stonesFri Apr 18 1997 12:3316
>      int fseek(
>              FILE *stream,
>              long int offset,     <---
>              int whence);
>
>    	int p1, p2, len;
>    	p1 = litPointers[6] * 256 + litPointers[7];
>    		:
>    	fseek(LitFV, 2048 + p1, 0);

The compiler should compute litPointers[6]*256 + litPointers[7], and store
this value into p1.  If the value doesn't fit in a signed int, the behavior
from this point onward is undefined.  Then the compiler should compute
p1+2048 (as an int -- if it doesn't fit, behavior is undefined again).  Then
the compiler should convert the result to the proper type for the call --
in this case, it should convert it to long int.  Finally, it makes the call.
3541.2have I understood this?GIDDAY::STRAUSStalking through my binocularsSun Apr 20 1997 22:2213
    Thanks for the quick response.
    Just to be sure I understand this correctly ...
    
    If the value in 2048 + p1 can be stored in a signed int, then the
    compiler converts it to a long int before calling fseek?
    
    If either litPointers[6]*256 + litPointers[7] or 2048 + p1 is too large
    for an int, then the behaviour is undefined?
    
    Hope I've got this right.
    Thanks again
    
    	leon
3541.3Yes, you do understand it - what is the customer's problem?DECC::MDAVISMark Davis - compiler maniacMon Apr 21 1997 14:0828
Using V5.5, cxx compiles the following with no errors, and the generated
code looks correct:

typedef int FILE;

extern "C"      int fseek(
              FILE *stream,
              long int offset,    // <---
              int whence);
 
int litPointers[10];
FILE *LitFV;

main(){
    	int p1, p2, len;
    	p1 = litPointers[6] * 256 + litPointers[7];

    	fseek(LitFV, 2048 + p1, 0);
}

Did the customer have a compile error or runtime error?  Was the customer
getting an (unreported) overflow on the assignment to p1, which then made
the fseek find the incorrect item?  (If so, this is a user error, since
the result is undefined according to the standard.)  The simple solution is
to define p1 as a long int....

Mark Davis
c/c++ team
3541.4"long p1" only helps p1+2048WIBBIN::NOYCEPulling weeds, pickin' stonesMon Apr 21 1997 14:429
> Was the customer getting an (unreported) overflow on the assignment to p1,
> [...] The simple solution is to define p1 as a long int....

Well, no, Mark, if the calculation of P[6]*256+P[7] as an int overflows,
it's already too late.  In addition to making p1 a long, you would need to
rewrite the expression to do the computation in 'long'.  Changing 256 to
256L should be enough:
	long p1;
    	p1 = litPointers[6] * 256L + litPointers[7];
3541.5Bill's correct (as always)DECC::MDAVISMark Davis - compiler maniacMon Apr 21 1997 14:472
Though I guessed as to the type of litPointers - if they're already
declared "long", then it's only the assignment that truncates....
3541.6the real problem ...GIDDAY::STRAUSStalking through my binocularsMon Apr 21 1997 21:4214
    Thanks everyone. I can now confidently explain to the customer that his
    code has a potential problem.
    
    Of course, this is not the _real_ problem ...
    Ths customer believes he's discovered a bug in the way UNIX handles
    file i/o buffers.  The code fragment came from a program he wrote to
    illustrate this.
    
    I wanted to be sure that his code was good before I start picking the
    UNIX kernel to pieces ;-)
    
    Thanks again
    
    	leon
3541.7unsigned char litPointers[2048];GIDDAY::STRAUSStalking through my binocularsTue Apr 22 1997 00:412
    BTW, for the record, litPointers is decalred as
    unsigned char  litPointers[2048];
3541.8before you throw too many stones...WIBBIN::NOYCEPulling weeds, pickin' stonesTue Apr 22 1997 12:318
>    	p1 = litPointers[6] * 256 + litPointers[7];

With litPointers declared as an array of unsigned char, this code now
looks as if it's depending on big-endian data layout of some buffer.
Has this code previously run on little-endian machines (such as PC's)?
What is the source of the data in the litPointers array?

Just some things to think about...
3541.9yes! big-endian dataGIDDAY::STRAUSStalking through my binocularsWed Apr 23 1997 00:1929
    Thanks for the suggestion in .8!
    
    The customer has told me that the code was originally developed
    on SCO UNIX and run on SCO, Solaris, SunOS and PCs.
    
    As you suspected, they've coded for a big-endian machine.
    The customer tells me this about his data ...
    
    >   The file 'literals.tcr' consists of 1024 2-byte pointers, =
    >followed by concatenated, non terminated character strings.
    
    I'm still waiting for a copy of this 'literals.tcr' file.
    
    Here's another code fragment to show how he reads litPointers from
    'literals.tcr' ...
    
    LitFV = fopen("literals.tcr", "r");
            int IsErrM = 0;
    
        if (LitFV)
        { fseek(LitFV, 0, 0);
              fread(litPointers, 2048, 1, LitFV);
        } else
          IsErrM = 1;
    
    Would it help if I posted the whole (270 line) test program?
    Thanks for all the interest adn help so far.
    
    	leon
3541.10yes seeing the program would helpDECC::OUELLETTEmudseason into blackfly seasonThu Apr 24 1997 23:341
x86 PCs are little-endian.  The others are of course big-endian.
3541.11need to fix test data before posting the codeGIDDAY::STRAUSStalking through my binocularsMon Apr 28 1997 21:3311
The customer has just informed me that the test data
I was running through his program was suspect :-(

Once I get that straightened out, I'll post the program
and data (assuming of course that there really is a 
problem)

Thanks again for the sustained interest in this issue.
Please stay tuned.

	leon