Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Behavior of the code

Reply
Thread Tools

Behavior of the code

 
 
Joe Wright
Guest
Posts: n/a
 
      12-25-2007
jacob navia wrote:
> Joe Wright wrote:
>> jacob navia wrote:
>>> Joe Wright wrote:
>>>> jacob navia wrote:
>>>>> santosh wrote:
>>>>>>> I have changed the code as below
>>>>>>>
>>>>>>> #include <stdio.h>
>>>>>>> int main(void)
>>>>>>> {
>>>>>>> int x = 0x7fff;
>>>>>>> signed char y;
>>>>>>> y =(signed char) x;
>>>>>>> printf("%hhx\n", y);
>>>>>>> return 0;
>>>>>>>
>>>>>>>
>>>>>>> }
>>>>>>> Now is it guaranteed that y will hold ff which is the last byte
>>>>>>> of x ?
>>>>>>>
>>>>>>> Now the output is ffffffff
>>>>>>> Why it is not ff only ?
>>>>>>
>>>>>> I get 'ff' here. What compiler are you using and what are the options
>>>>>> that you are passing it?
>>>>>>
>>>>>
>>>>> I get ff here too
>>>>>
>>>> I took the liberty of changing the code again..
>>>>
>>>> #include <stdio.h>
>>>> int main(void)
>>>> {
>>>> int x = 0x7fff;
>>>> char y;
>>>> y = x;
>>>> printf("%hx\n", y);
>>>> return 0;
>>>> }
>>>> None of the casting was necessary and "%hhx" is weird. This prints
>>>> ffff just as I expect it to. What is the case for ff?
>>>>
>>>
>>> See my other reply. I think Microsoft has a bug here
>>>

>> My compiler is gcc (djgpp) and I get ffff. If msvc gets ffff too I
>> don't see the 'bug' you suggest. Once x is assigned to y the value of
>> y is -1. In the printf the value of y is promoted to int (still -1)
>> and displayed as unsigned short (ffff). In order to print ff the value
>> of y must be 255 and there is no case for that here. Could be lcc-win
>> is broke.
>>

>
>
> I was speaking about the second version, and did not see that you
> have changed it AGAIN. After that change I get ffff again.
>
> The bug I was referring to was for this code
> #include <stdio.h
> int main(void)
> {
> int x = 0x7fff;
> signed char y;
> y =(signed char) x;
> printf("%hhx\n", y);
> return 0;
>
>
> }

Bug? I reformatted the above code and fixed the stdio.h invocation..

#include <stdio.h>
int main(void)
{
int x = 0x7fff;
signed char y;
y = (signed char) x;
printf("%hhx\n", y);
return 0;
}

...and I still get ffff as I expect. If you get ff please explain why and
also explain the "%hhx" format string.

Joyeux Noel

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
 
Reply With Quote
 
 
 
 
jacob navia
Guest
Posts: n/a
 
      12-25-2007
Joe Wright wrote:
>> The bug I was referring to was for this code
>> #include <stdio.h
>> int main(void)
>> {
>> int x = 0x7fff;
>> signed char y;
>> y =(signed char) x;
>> printf("%hhx\n", y);
>> return 0;
>>
>>
>> }

> Bug? I reformatted the above code and fixed the stdio.h invocation..
>
> #include <stdio.h>
> int main(void)
> {
> int x = 0x7fff;
> signed char y;
> y = (signed char) x;
> printf("%hhx\n", y);
> return 0;
> }
>
> ..and I still get ffff as I expect. If you get ff please explain why and
> also explain the "%hhx" format string.
>
> Joyeux Noel
>


[root@gateway tmp]# cat thh.c
#include <stdio.h>
int main(void)
{
int x = 0x7fff;
signed char y;
y =(signed char) x;
printf("%hhx\n", y);
return 0;
}
[root@gateway tmp]# gcc thh.c
[root@gateway tmp]# ./a.out
ff
[root@gateway tmp]# gcc -v
Reading specs from /usr/lib/gcc-lib/i586-mandrake-linux-gnu/2.96/specs
gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)



--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
 
Reply With Quote
 
 
 
 
Thomas Lumley
Guest
Posts: n/a
 
      12-25-2007
On Dec 25, 3:52 am, santosh <(E-Mail Removed)> wrote:
> somenath wrote:
>
> <snip>
>
> > I am unable to understand the conversation
> > Let me explain my understanding .

>
> > int x = 0xFFFFFFF0;
> > signed char y;
> > y = x;

>


> > Now when I print using %x it should print the hexadecimal
> > representation of 240 i.e F0 .Why it is printing fffffff0 ?

>
> Because of format specifier mismatch. You are supplying a char and
> telling it to look for an int. As a result, printf accesses more bytes
> than it should and prints whatever happens to be in the extra bytes.
> Use the 'hhx' format specifier and try again. Also use a cast for the
> assignment to 'y'.


A clarification: this sounds as though you mean that printf() is
accessing memory it isn't supposed to (which would undefined
behaviour). The argument to printf() *is* an int because of the
default argument promotions, and so %x is a perfectly valid
specifier, it just doesn't give the output that the OP expected.

-thomas
 
Reply With Quote
 
Joe Wright
Guest
Posts: n/a
 
      12-25-2007
jacob navia wrote:
> Joe Wright wrote:
>>> The bug I was referring to was for this code
>>> #include <stdio.h
>>> int main(void)
>>> {
>>> int x = 0x7fff;
>>> signed char y;
>>> y =(signed char) x;
>>> printf("%hhx\n", y);
>>> return 0;
>>>
>>>
>>> }

>> Bug? I reformatted the above code and fixed the stdio.h invocation..
>>
>> #include <stdio.h>
>> int main(void)
>> {
>> int x = 0x7fff;
>> signed char y;
>> y = (signed char) x;
>> printf("%hhx\n", y);
>> return 0;
>> }
>>
>> ..and I still get ffff as I expect. If you get ff please explain why
>> and also explain the "%hhx" format string.
>>
>> Joyeux Noel
>>

>
> [root@gateway tmp]# cat thh.c
> #include <stdio.h>
> int main(void)
> {
> int x = 0x7fff;
> signed char y;
> y =(signed char) x;
> printf("%hhx\n", y);
> return 0;
> }
> [root@gateway tmp]# gcc thh.c
> [root@gateway tmp]# ./a.out
> ff
> [root@gateway tmp]# gcc -v
> Reading specs from /usr/lib/gcc-lib/i586-mandrake-linux-gnu/2.96/specs
> gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)
>

I can do that too.

C:\work\c\clc>cat xx1.c
#include <stdio.h>
int main(void)
{
int x = 0x7fff;
signed char y;
y = (signed char) x;
printf("%hhx\n", y);
return 0;
}

C:\work\c\clc>gcc xx1.c -o xx1.exe

C:\work\c\clc>xx1
ffff

C:\work\c\clc>gcc --version
gcc.exe (GCC) 3.1
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Do you think 2.96 is broken? I think ffff is right and you think ff is
right. I ask you again to explain why.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      12-25-2007
Joe Wright wrote:
> Do you think 2.96 is broken? I think ffff is right and you think ff is
> right. I ask you again to explain why.
>


The C standard fprintf function.
<quote>
hh
Specifies that a following d, i, o, u, x, or X conversion specifier
applies to a signed char or unsigned char argument (the argument will
have been promoted according to the integer promotions, but its value
shall be converted to signed char or unsigned char before printing); or
that a following n conversion specifier applies to a pointer to a signed
char argument.
<end quote>

Since you specify the "x" format, the value is
interpreted as unsigned, and it is converted to an
unsigned char.

It is not lcc-win that is wrong but gcc 3.1

The 2.96 version apparently wasn't broken.


--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
 
Reply With Quote
 
Joe Wright
Guest
Posts: n/a
 
      12-25-2007
jacob navia wrote:
> Joe Wright wrote:
>> Do you think 2.96 is broken? I think ffff is right and you think ff is
>> right. I ask you again to explain why.
>>

>
> The C standard fprintf function.
> <quote>
> hh
> Specifies that a following d, i, o, u, x, or X conversion specifier
> applies to a signed char or unsigned char argument (the argument will
> have been promoted according to the integer promotions, but its value
> shall be converted to signed char or unsigned char before printing); or
> that a following n conversion specifier applies to a pointer to a signed
> char argument.
> <end quote>
>
> Since you specify the "x" format, the value is
> interpreted as unsigned, and it is converted to an
> unsigned char.
>
> It is not lcc-win that is wrong but gcc 3.1
>
> The 2.96 version apparently wasn't broken.
>
>

Thanks. The "%hhx" had escaped me until now. I'm going to have to ask DJ
about this now. Thanks again.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      12-25-2007
[There was much snippage and I am not 100% sure that the attributions
here are correct, but I think:]

>> somenath wrote:
>>> int x = 0xFFFFFFF0;
>>> signed char y;
>>> y = x;


In article <(E-Mail Removed)>
somenath <(E-Mail Removed)> wrote:
>I have changed the code as below
>
>#include <stdio.h>
>int main(void)
>{
> int x = 0x7fff;
> signed char y;
> y =(signed char) x;
> printf("%hhx\n", y);
> return 0;
>
>
>}
>Now is it guaranteed that y will hold ff which is the last byte of x ?


No, unless ... well, I will get to that in a moment.

>Now the output is ffffffff
>Why it is not ff only ?


The "hh" modifier is new in C99; C89 does not have it, and if you are
using a C89 system (rather than a C99 one -- and C99 systems are still
rather rare, so even if your compiler supports *some* C99 features, it
probably is not actually a C99 implementation, and may not support the
hh modifier), the result is unpredictable.

In C99, "%hhx" in printf() says that the argument is an int or unsigned
int resulting from widening an unsigned char, and should be narrowed
back to an unsigned char and then printed otherwise the same as "%x".
In C89, most printf engines are likely to implement this as "%hx" or
just plain "%x", and yours appears to do the latter.

Let me go back to the original version for a moment:

int x = 0xFFFFFFF0;
signed char y;
y = x;

and let us further consider two actual implementations, one on a PDP-11
(16-bit int, 32-bit long, two's complement) and one on a Univac (18-bit
int, 36-bit long, ones' complement).

The expression

0xFFFFFFF0

has type "unsigned long" on the PDP-11, because the value is
4294967280, which exceeds INT_MAX (32767) and LONG_MAX (2147483647)
but not ULONG_MAX (4294967295). It has type "long" on the Univac,
because the value exceeds INT_MAX (131071) but not LONG_MAX
(34359738367).

This value does not fit in an "int" on either machine, but both
happen to merely "chop off" excess bits in assignment (I think --
I know this is how the PDP-11 works; the Univac compiler is more
opaque). On the PDP-11, then, assigning this value to the 16-bit
signed int named "x" results in setting the bits of x to 0xfff0,
which represents -16. On the Univac, it sets the 18-bit signed
int to 0x3fff0, which represents -15. (See
<http://web.torek.net/torek/c/numbers.html> for an explanation of
ones' and two's complement.)

Luckily, the values -16 and -15 are both always in range for a
"signed char", which must be able to hold values between -127 and
127 inclusive. So, on the PDP-11, the assignment to y sets y to
-16, and on the Univac, it sets it to -15. These have bit patterns
0xfff0 and 0x3fff0 respectively. If you then pass these values to
printf() using the "%x" format, you will see fff0 (on the PDP-11)
and 3fff0 (on the Univac).

(Aside: "%x" expects an unsigned int, but a signed char converts
to a signed int on all C systems. The C standards have text that
implies that this is "supposed to work" -- you are supposed to be
able to pass values of types that are correct in all but signedness
-- but does not come right out and demand that implementations
*make* it work. It may be wise to avoid depending on it, at least
in some situations.)

[Note that a C implementation is allowed, but not required, to
catch the fact that 4294967280 does not fit in an ordinary "int".
So it is possible that the code will not compile, or that if it
does compile, it might not run. In general, however, people who
buy computers are most interested in getting the wrong answer as
fast as possible , so they tend to overlook things like
reliability and bug-detection in favor of whatever system has the
most gigahertz or teraflops. Computer-system-makers usually indulge
these customers: there is no point in working long and hard to
build a system that no one will buy. In some cases, like flight
control systems on airplanes or computers inside medical devices,
people are actually willing to pay for correctness. More seriously,
it is a matter of trade-offs: correctness is not so important in
a handheld game machine, but incorrect operation of the brakes in
your car could be disastrous. Unfortunately for those who *want*
reliability, "fast because we omitted all the correctness-checking"
tends to be the default -- we have to add our own checking.]

In the second, modified version, the code now reads:

int x = 0x7fff;
signed char y;
y =(signed char) x;

The constant 0x7fff has value 32767. All C systems are required
to have INT_MAX be at least 32767 (as, e.g., on the PDP-11; it may
be larger, as, e.g., on most Intel-based systems like the one you
are no doubt using). So 32767 has type "int" and fits in "x",
eliminating a lot of concerns.

The "signed char" type, however, need only hold values in -127 to
127. Chances are that your system, whatever it is, holds values
in -128 to 127. On the Univac, which has 9-bit "char"s, it holds
values in -255 to 255 inclusive (not -256, just -255). Conversion
from plain (signed) int to signed char can produce implementation-defined
results, if the value of the "int" does not fit in the "signed
char" (as is generally the case here). (I seem to recall that the
wording for casts is slightly different from that for ordinary
assignments, but cannot find the text in the Standard at the moment.)

Thus, there is no guarantee that y will hold "ff" (as a bit pattern)
-- and on the Univac, it probably holds 0x1ff as a bit pattern,
which represents the value -0 (negative zero). Whether you consider
a 9-bit byte a "byte" is also not clear to me (but I note that the
C Standard does: it says that a "byte" is a char, however many bits
that may be).

Finally, consider the phrasing of this question:

>Now is it guaranteed that y will hold ff which is the last byte of x ?


The whole concept of "last byte" is rather fuzzy: which byte(s)
are "first" and which are "last"? On an 8-bit little-endian machine,
like the Intel based systems most people are most familiar with,
the least significant byte comes *first* in numerical order, not
last. I believe it is better to think not in terms of "machine
byte order" -- which is something you can only control by picking
which machines you use -- but rather to think in terms of values
and representations. As a C programmer, you have a great deal of
control of values, and if you use "unsigned" types, you have complete
control of representations. For instance, you can read a 10-bit
two's complement value from a stdio stream, with the first input
char giving the uppermost 2 bits, using "unsigned int" this way:

/*
* Read one 2-bit value and one 8-bit value from the given stream,
* and compose a signed 10-bit value (in the range [-512..+511])
* from those bits.
*/
int get_signed_10_bit_value(FILE *fp) {
int c0, c1;
unsigned int val;

c0 = getc(fp);
if (c0 == EOF) ... handle error ...
c1 = getc(fp);
if (c1 == EOF) ... handle error ...
val = ((c0 & 0x03) << | (c1 & 0xff);
return (val ^ 0x200) - 0x200;
}

(Note that when you go to read more than 15 bits, you need to be
careful with intermediate values, since plain int may have as few
as 15 non-sign "value bits", and unsigned int may have as few as
16. You will need to convert values to "unsigned long", using
temporary variables, casts, or both.)

This xor-and-subtract trick works on all implementations, including
ones' complement machine like the Univac. Its only real limitation
is that the final (signed) value has to fit in the types available:
a 16-bit two's complement machine has a -32768 but a 16-bit ones'
complement machine bottoms out at -32767. (As it happens, though,
anything other than two's complement is rare today, so you probably
need not worry about this very much.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
somenath
Guest
Posts: n/a
 
      12-26-2007
On Dec 26, 4:58 am, Chris Torek <(E-Mail Removed)> wrote:
> [There was much snippage and I am not 100% sure that the attributions
> here are correct, but I think:]
>
> >> somenath wrote:
> >>> int x = 0xFFFFFFF0;
> >>> signed char y;
> >>> y = x;

>
> In article <(E-Mail Removed)>
>
> somenath <(E-Mail Removed)> wrote:
> >I have changed the code as below

>
> >#include <stdio.h>
> >int main(void)
> >{
> > int x = 0x7fff;
> > signed char y;
> > y =(signed char) x;
> > printf("%hhx\n", y);
> > return 0;

>
> >}
> >Now is it guaranteed that y will hold ff which is the last byte of x ?

>
> No, unless ... well, I will get to that in a moment.
>
> >Now the output is ffffffff
> >Why it is not ff only ?

>
> The "hh" modifier is new in C99; C89 does not have it, and if you are
> using a C89 system (rather than a C99 one -- and C99 systems are still
> rather rare, so even if your compiler supports *some* C99 features, it
> probably is not actually a C99 implementation, and may not support the
> hh modifier), the result is unpredictable.
>
> In C99, "%hhx" in printf() says that the argument is an int or unsigned
> int resulting from widening an unsigned char, and should be narrowed
> back to an unsigned char and then printed otherwise the same as "%x".
> In C89, most printf engines are likely to implement this as "%hx" or
> just plain "%x", and yours appears to do the latter.
>
> Let me go back to the original version for a moment:
>
> int x = 0xFFFFFFF0;
> signed char y;
> y = x;
>
> and let us further consider two actual implementations, one on a PDP-11
> (16-bit int, 32-bit long, two's complement) and one on a Univac (18-bit
> int, 36-bit long, ones' complement).
>
> The expression
>
> 0xFFFFFFF0
>
> has type "unsigned long" on the PDP-11, because the value is
> 4294967280, which exceeds INT_MAX (32767) and LONG_MAX (2147483647)
> but not ULONG_MAX (4294967295). It has type "long" on the Univac,
> because the value exceeds INT_MAX (131071) but not LONG_MAX
> (34359738367).
>
> This value does not fit in an "int" on either machine, but both
> happen to merely "chop off" excess bits in assignment (I think --
> I know this is how the PDP-11 works; the Univac compiler is more
> opaque). On the PDP-11, then, assigning this value to the 16-bit
> signed int named "x" results in setting the bits of x to 0xfff0,
> which represents -16. On the Univac, it sets the 18-bit signed
> int to 0x3fff0, which represents -15. (See
> <http://web.torek.net/torek/c/numbers.html> for an explanation of
> ones' and two's complement.)
>
> Luckily, the values -16 and -15 are both always in range for a
> "signed char", which must be able to hold values between -127 and
> 127 inclusive. So, on the PDP-11, the assignment to y sets y to
> -16, and on the Univac, it sets it to -15. These have bit patterns
> 0xfff0 and 0x3fff0 respectively. If you then pass these values to
> printf() using the "%x" format, you will see fff0 (on the PDP-11)
> and 3fff0 (on the Univac).
>
> (Aside: "%x" expects an unsigned int, but a signed char converts
> to a signed int on all C systems. The C standards have text that
> implies that this is "supposed to work" -- you are supposed to be
> able to pass values of types that are correct in all but signedness
> -- but does not come right out and demand that implementations
> *make* it work. It may be wise to avoid depending on it, at least
> in some situations.)
>
> [Note that a C implementation is allowed, but not required, to
> catch the fact that 4294967280 does not fit in an ordinary "int".
> So it is possible that the code will not compile, or that if it
> does compile, it might not run. In general, however, people who
> buy computers are most interested in getting the wrong answer as
> fast as possible , so they tend to overlook things like
> reliability and bug-detection in favor of whatever system has the
> most gigahertz or teraflops. Computer-system-makers usually indulge
> these customers: there is no point in working long and hard to
> build a system that no one will buy. In some cases, like flight
> control systems on airplanes or computers inside medical devices,
> people are actually willing to pay for correctness. More seriously,
> it is a matter of trade-offs: correctness is not so important in
> a handheld game machine, but incorrect operation of the brakes in
> your car could be disastrous. Unfortunately for those who *want*
> reliability, "fast because we omitted all the correctness-checking"
> tends to be the default -- we have to add our own checking.]
>
> In the second, modified version, the code now reads:
>
> int x = 0x7fff;
> signed char y;
> y =(signed char) x;
>
> The constant 0x7fff has value 32767. All C systems are required
> to have INT_MAX be at least 32767 (as, e.g., on the PDP-11; it may
> be larger, as, e.g., on most Intel-based systems like the one you
> are no doubt using). So 32767 has type "int" and fits in "x",
> eliminating a lot of concerns.
>
> The "signed char" type, however, need only hold values in -127 to
> 127. Chances are that your system, whatever it is, holds values
> in -128 to 127. On the Univac, which has 9-bit "char"s, it holds
> values in -255 to 255 inclusive (not -256, just -255). Conversion
> from plain (signed) int to signed char can produce implementation-defined
> results, if the value of the "int" does not fit in the "signed
> char" (as is generally the case here). (I seem to recall that the
> wording for casts is slightly different from that for ordinary
> assignments, but cannot find the text in the Standard at the moment.)
>
> Thus, there is no guarantee that y will hold "ff" (as a bit pattern)
> -- and on the Univac, it probably holds 0x1ff as a bit pattern,
> which represents the value -0 (negative zero). Whether you consider
> a 9-bit byte a "byte" is also not clear to me (but I note that the
> C Standard does: it says that a "byte" is a char, however many bits
> that may be).
>
> Finally, consider the phrasing of this question:
>
> >Now is it guaranteed that y will hold ff which is the last byte of x ?

>
> The whole concept of "last byte" is rather fuzzy: which byte(s)
> are "first" and which are "last"? On an 8-bit little-endian machine,
> like the Intel based systems most people are most familiar with,
> the least significant byte comes *first* in numerical order, not
> last. I believe it is better to think not in terms of "machine
> byte order" -- which is something you can only control by picking
> which machines you use -- but rather to think in terms of values
> and representations. As a C programmer, you have a great deal of
> control of values, and if you use "unsigned" types, you have complete
> control of representations. For instance, you can read a 10-bit
> two's complement value from a stdio stream, with the first input
> char giving the uppermost 2 bits, using "unsigned int" this way:
>
> /*
> * Read one 2-bit value and one 8-bit value from the given stream,
> * and compose a signed 10-bit value (in the range [-512..+511])
> * from those bits.
> */
> int get_signed_10_bit_value(FILE *fp) {
> int c0, c1;
> unsigned int val;
>
> c0 = getc(fp);
> if (c0 == EOF) ... handle error ...
> c1 = getc(fp);
> if (c1 == EOF) ... handle error ...
> val = ((c0 & 0x03) << | (c1 & 0xff);
> return (val ^ 0x200) - 0x200;
> }
>
> (Note that when you go to read more than 15 bits, you need to be
> careful with intermediate values, since plain int may have as few
> as 15 non-sign "value bits", and unsigned int may have as few as
> 16. You will need to convert values to "unsigned long", using
> temporary variables, casts, or both.)
>
> This xor-and-subtract trick works on all implementations, including
> ones' complement machine like the Univac. Its only real limitation
> is that the final (signed) value has to fit in the types available:
> a 16-bit two's complement machine has a -32768 but a 16-bit ones'
> complement machine bottoms out at -32767. (As it happens, though,
> anything other than two's complement is rare today, so you probably
> need not worry about this very much.)


While going through this article I got an one question i.e how compile
decides if it is negative number?
For example in the bellow code
#include <stdio.h>

int main(int argc, char *argv[])
{
signed char c = 128;

printf("value of C = %d\n",c);
return 0;
}

Output of the program is
value of C = -128

My question is how compiler understans if C is equal to -128.

The binary representation of 128 is 10000000
In two's complement system 10000000 also means 128 so how compile
assign the value -128 to c ?

I guessed one possibility. Please correct me if I am wrong.
Complier know the sizeof char and SCHAR_MAX and it found that 128 >
SCHAR_MAX .So it treats binary representation of 128 as the negative
number representation and incidentally it is -128 so it assign -128 to
C .
Is it not correct?




 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      12-26-2007
somenath wrote:
....
> While going through this article I got an one question i.e how compile
> decides if it is negative number?
> For example in the bellow code
> #include <stdio.h>
>
> int main(int argc, char *argv[])
> {
> signed char c = 128;
>
> printf("value of C = %d\n",c);
> return 0;
> }
>
> Output of the program is
> value of C = -128
>
> My question is how compiler understans if C is equal to -128.


That's up to the implementation, you'll have to read the
implementation's documentation to find out the method it uses. The
standard doesn't cover this.

> The binary representation of 128 is 10000000
> In two's complement system 10000000 also means 128 so how compile
> assign the value -128 to c ?
>
> I guessed one possibility. Please correct me if I am wrong.
> Complier know the sizeof char and SCHAR_MAX and it found that 128 >
> SCHAR_MAX .So it treats binary representation of 128 as the negative
> number representation and incidentally it is -128 so it assign -128 to
> C .
> Is it not correct?


The result you see is possible only if 128 > SCHAR_MAX. In that case,
the token 128 is interpreted as an integer literal of type 'int' with a
value of 128. When this value is converted to signed char, because 128 >
SCHAR_MAX, an implementation is allowed to either raise an
implementation-defined signal, or to produce an implementation-defined
result. As a result you should NEVER do this unless you're writing code
that is deliberately and with good justification intended to be
non-portable. In that case, you would have to look at implementation's
documentation to determine what the results would be.

If the implementation raises a signal on signed overflow, you'll need to
write a signal handler, and register it as handling that specific
signal, in order for such code to serve any (debatably) useful purpose.

If the implementation produces an implementation-defined result, you'll
need to find out what it is, and decide whether or not it's useful for
your purposes. However, if it is useful to write 128 and have it convert
to signed char as -128 (as the implementation you're using apparently
does), then surely you would be better off writing -128 in the first place?
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      12-26-2007
somenath <(E-Mail Removed)> writes:

> On Dec 26, 4:58 am, Chris Torek <(E-Mail Removed)> wrote:
>> [There was much snippage and I am not 100% sure that the attributions
>> here are correct, but I think:]
>>
>> >> somenath wrote:
>> >>> int x = 0xFFFFFFF0;
>> >>> signed char y;
>> >>> y = x;


<snip very helpful article about signed numbers and representations>

> While going through this article I got an one question i.e how compile
> decides if it is negative number?
> For example in the bellow code
> #include <stdio.h>
>
> int main(int argc, char *argv[])
> {
> signed char c = 128;
>
> printf("value of C = %d\n",c);
> return 0;
> }
>
> Output of the program is
> value of C = -128
>
> My question is how compiler understans if C is equal to -128.
>
> The binary representation of 128 is 10000000


You will get into a lot of trouble if think too much about
representations and bit patterns. Representations matter, but much
less than most beginners think they do.

In C, the literal 128 means 128. It never means anything else. You
can't write a negative integer constant in C. The type of an integer
constant depends on the sizes of some of the integer types in your
implementation, but in this case we can be sure it will be of type
'int' because C guarantees that int is always big enough to hold 128,
and int is the smallest integer type that the compiler will "try" (if
the value is too big it will be the first of 'long int' or 'long long
int' that is big enough.

[All this is about C99 and excludes the possibility of extended
integer types that some implementations provide. For the "full
monty" you need to read up on how octal and hex constants are
treated and how adding l, ll and u suffixes can change things, but
lets keep this simple.]

OK, so 128 means 128. There are then two issues to understand. What
happens when 128 is assigned to a variable of type 'signed char' and
what happens in the printf call. I *think* these have been explained
well enough, but I am happy to have a go if you think otherwise!

--
Ben.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Odd behavior with odd code Michael Speer C Programming 33 02-18-2007 07:31 AM
Do you think this code will produce any undefined behavior? Chris Thomasson C++ 10 11-17-2006 06:10 PM
THE BEHAVIOR CODE FOR 24-BITUP/DOWN COUNTER WITH PARALLEL LOAD AND ASYNCHRONOUS RESET coldplay112 VHDL 2 09-25-2006 10:06 AM
Step-thru code - odd behavior ASP .Net 2 06-01-2004 06:10 PM
undefined behavior or not undefined behavior? That is the question Mantorok Redgormor C Programming 70 02-17-2004 02:46 PM



Advertisments