Ja, är inte det där det klassiska problemet att om du multiplicerar två vanliga int så måste resultatet rymmas i en int, att det till vänster om likhetstecknet rymmer mer hjälper inte.
I det andra fallet så är det andra talet större än vad som ryms i en int, alltså castas hela högerledet till long (eller nåt sånt).
Att explicit casta till long är väl det rätta sättet, det ska väl formellt sett räcka med att den ena faktorn castas.
$ cc mult
data2 = 0xf6 * 16777216;
........^
%CC-W-INTOVERFL, In this statement, integer overflow occurs in evaluating the expression "0X00000000000000F6*16777216".
at line number 9 in file USER:[JANNE]MULT.C;1
$
$ cc mult2
data2 = 0xf6 * 11116777216;
........^
%CC-I-INTCONSTTRUNC, In this statement, conversion of the constant "0X00000000000000F6*11116777216" to unsigned long type will cause data loss.
at line number 9 in file USER:[JANNE]MULT2.C;1
$
$ help cc message INTOVERFL
CC
Messages
INTOVERFL
Message <Context> integer overflow occurs in evaluating the
expression "<expression>".
Description An integer overflow occurred while evaluating a
constant expression. The value of the expression is
undefined.
User Action Correct the constant expression so that it does not
overflow.
$ help cc message INTCONSTTRUNC
CC
Messages
INTCONSTTRUNC
Message <Context> conversion of the constant "<constant>" to
<type> type will cause data loss.
Description A constant is converted to a type that is too small
to hold the constant value. Data will be lost in the
conversion.
User Action If this is what you intended, cast the constant to
the desired type. You might also want to mask off
the high-order bits before casting in order to avoid
optional message intconcasttru, which reports data
loss caused by casts.
$ cc mult
data2 = 0xf6 * 16777216;
........^
%CC-W-INTOVERFL, In this statement, integer overflow occurs in evaluating the expression "0X00000000000000F6*16777216".
at line number 9 in file USER:[JANNE]MULT.C;1
$
$ link mult
%LINK-W-WRNERS, compilation warnings in module MULT file USER:[JANNE]MULT.OBJ;11
$
$ run mult
4127195136
$
Det har väl med att göra att värderna var valda så att det ändå fungerar...
För mig så blev det ju en "Warning" i första fallet och en "Information"
i det andra. Du verkade inte få något i andra fallet, men det
skiljer säkert mellan kompilatorer. Om jag drar på "känsligheten"
så klagar min kompilator på andra saker som inte har med
just multiplikationen att göra...
för mig blev det helgalet då jag använde samma rad i ett program där hex konstaten var ett 8 bitars värde utläst från en fil...
det funkade om värdet i filen var litet typ < 0x30, för större tal räknade den kapitalt fel..
data2 = (unsigned char)fileData[30] * 16777216
värdet i filen är 0xf6
där blev data2 = 18446744073541779456 istf 4127195136
data2 = (unsigned char) 0xf6 * 16777216;
........^
%CC-W-INTOVERFL, In this statement, integer overflow occurs in evaluating the expression "(unsigned char)0X00000000000000F6*16777216".
at line number 7 in file USER:[JANNE]MULT4.C;2
Om jag lägger till "(unsigned int) 16777216" så försvinner varningen.
Det ger dock "rätt" svar i båda fallen...
$ cc mult4.c/list/mach/noopt/warn=(enab=level6,verbose)
void main( void )
^
%CC-I-MAINNOTINT, Strict standard C extension: The declaration of the "main" function has a return type other than int.
at line number 3 in file USER:[JANNE]MULT4.C;11
Description: Standard C requires that the "main" function be defined with a return type of int. HP C will accept other
return types, but the program does not conform to the C standard. The status value returned to the environment
may not be what you expect, and other C compilers may not accept the definition as written.
User Action: Define the "main" function with a return type of int for maximal portability.
data2 = in1 * 16777216;
........^
%CC-I-VALUEPRES, In this statement, the conversion of the unsigned char/short value "in1" to signed int shows one
example of this program's use of value-preserving integral promotion. This differs from the unsigned-preserving
semantics of some older C compilers.
at line number 11 in file USER:[JANNE]MULT4.C;11
Description: This expression shows one of possibly many places where this compilation uses value-preserving
semantics for small integer promotions rather than unsigned-preserving semantics used by some older compilers.
In cases where an unsigned char or unsigned short int is promoted to an integer, there are two different ways
the convert could happen. Standard C requires that the type be converted to a signed int (value-preserving
semantics) while some older compilers will convert to an unsigned int (unsigned-preserving semantics). The
difference in the choice of int or unsigned int can have an impact on results of expressions that use the converted
value. The compiler cannot determine whether or not a particular instance of this usage will cause an observable
behavior difference in the program. For more information, consult Section 3.2.1.1 of the "Rationale for ANSI C".
User Action: Be aware that older, non-standard compilers might interpret this expression differently.
printf("%lu\n", data2);
^
%CC-I-IGNORECALLVAL, In this statement, the value returned from the function "printf(...)" is not used - if this
is intended, it should be cast to "void".
at line number 12 in file USER:[JANNE]MULT4.C;11
Description: A function that returns a value has been invoked, yet the value was not used. This might not have
been what you intended.
User Action: Cast the function to void to suppress the message.
$
Jag får varningen vid värden på konstaten som är 0x80 eller högre
För 0x7F eller lägre försvinner varningen. Har sannolikt med signed
att göra (d.v.s om högsta biten är satt eller inte). Explicit cast
till unsigned löser ju det...
Det beror oftast på att kompilern är ställd till att alla icke-castade konstanter ska behandlas som signed. Det är ett val man ofta kan ställa i kompilern.
Samtidig anser jag att man aldrig ska ha icke-castade värden så det är ju en idé att casta alla värden alla gångar.
data2 = 0xf6 * 16777216;
........^
%CC-I-INTCONSTSIGN, In this statement, conversion of the constant "0X00000000000000F6*16777216" to
unsigned long type will cause a change in sign.
at line number 10 in file USER:[JANNE]MULT4.C;17
Description: Either an unsigned type was assigned a negative constant value, or a signed type was
assigned a positive contant value which will be evalated as a negative number after the assignment.
Note that this message is not output for assignments to 1-bit bit fields. The message bitconstsign
is generated in that case.
User Action: If this is what you intended, cast the constant to the desired type. You might also want
to change the constant to the correct signed or unsigned value in order to avoid the optional message
intconcastsgn, which reports sign changes caused by casts.
Varningen försvinner även med "data2 = 0xf6U * 16777216;"
Ett "U" efter värdet kanske är samma som som "(unsigned char)" före...
Helt klart blandas signed och unsigned
Ange alltid med U på konstanter för att förtydliga att det gäller unsigned. Sedan kan man fråga sig varför 0xFF är signed i C…
För att göra koden mer lättläst och underhållbar använd aldrig magic numbers i koden.