C Questions

A

aarklon

Hi all,

I was reading the book "C interview Questions" By J. Rajaram
published in india by firewall media, after going through the book
i have the following doubts

1) why the following program is not showing compilation error in the
lines no: of arguments in the function declaration and function
definition do not match???

void swap();

int main(void)
{

int x=10,y=8;

swap(&x,&y);
printf("\n x = %d y = %d",x,y);

puts("");
return(EXIT_SUCCESS);
}

void swap(int *a, int *b)
{

*a ^= *b,*b ^= *a, *a ^= *b;

}


2) why (~0 == (unsigned int)-1)
can any body explain???

from reading CLC book "C Unleashed" i know that -X =(MAX - X)+1
1.e -x =~x +1 ,so from this relation how can we get (~0 == (unsigned
int)-1)

3)why does printf("%d %f",14.0,2.50); gives o/p as 0 0.00000

4)why printf("%d",-1>>3); gives o/p as -1

5)
main()
{
int i= -1;
-i;
printf("i = %d -i = %d",i,-i);
}

the o/p is given as i = -1, -i =1

but when this pgm is run
main()
{
int i= -1;
+i;
printf("i = %d +i = %d",i,-i);
}

the o/p is given as i = -1, +i = -1

so what exactly is the purpose of unary + operator and unary -
operator??


6)
why the program
main()
{

int i=5; j=10;
i=i^=j ||i;
printf("i= %d",i);
}
gives o/p as 4???
as far my understanding goes result of an expression involving
logical operator is of boolean nature
 
B

Ben Pfaff

1) why the following program is not showing compilation error in the
lines no: of arguments in the function declaration and function
definition do not match???

void swap();

No prototype is given for this function, so the compiler cannot
check that the arguments are the correct types.

To prototype a function with no parameters, use void:
void swap(void);
*a ^= *b,*b ^= *a, *a ^= *b;

See the C FAQ:

20.15c: How can I swap two values without using a temporary?

A: The standard hoary old assembly language programmer's trick is:

a ^= b;
b ^= a;
a ^= b;

But this sort of code has little place in modern, HLL
programming. Temporary variables are essentially free,
and the idiomatic code using three assignments, namely

int t = a;
a = b;
b = t;

is not only clearer to the human reader, it is more likely to be
recognized by the compiler and turned into the most-efficient
code (e.g. using a swap instruction, if available). The latter
code is obviously also amenable to use with pointers and
floating-point values, unlike the XOR trick. See also questions
3.3b and 10.3.
2) why (~0 == (unsigned int)-1)
can any body explain???

It's not necessarily true. But on 2's complement machines, -1 is
represented by all-bits-one.
3)why does printf("%d %f",14.0,2.50); gives o/p as 0 0.00000

Actually it yields undefined behavior: %d takes an int argument,
but you're providing a double argument.
4)why printf("%d",-1>>3); gives o/p as -1

Shifting a negative number right invokes undefined behavior, but
most machines define it to propagate the sign bit to the right.
Since -1 is all-bits-one on your machine, this means that
shifting -1 to the right doesn't change any bits.
5)
main()
{
int i= -1;
-i;
printf("i = %d -i = %d",i,-i);
}

the o/p is given as i = -1, -i =1

but when this pgm is run
main()
{
int i= -1;
+i;
printf("i = %d +i = %d",i,-i);
}

the o/p is given as i = -1, +i = -1

Compiler bug?
i=i^=j ||i;

Undefined behavior. See the C FAQ, e.g.

3.3: I've experimented with the code

int i = 3;
i = i++;

on several compilers. Some gave i the value 3, and some gave 4.
Which compiler is correct?

A: There is no correct answer; the expression is undefined. See
questions 3.1, 3.8, 3.9, and 11.33. (Also, note that neither
i++ nor ++i is the same as i+1. If you want to increment i,
use i=i+1, i+=1, i++, or ++i, not some combination. See also
question 3.12.)
 
A

Ark Khasin

Ben said:
(e-mail address removed) writes:

It's not necessarily true. But on 2's complement machines, -1 is
represented by all-bits-one.
<snip>
Actually...

(unsigned int)-1:
-1 is out of unsigned range; to convert, need to add UINT_MAX. Got
UINT_MAX-1; it's in the range so it's the result of conversion.

~0:
0 has a (but not the) representation of all bits 0.
Assuming that ~ acts on value, not on representation (a murky issue
being battled out in another thread nearby), ~0 has a representation of
all bits 1.

==:
LHS is int, RHS is unsigned int. Need to convert LHS to unsigned int.
2's complement machine: ~0==-1. -1 is out of unsigned range; to convert,
need to add UINT_MAX. Got UINT_MAX-1; it's in the range so it's the
result of conversion. Compares equal to RHS.
sign+magnitude machine: ~0==-INT_MAX. -INT_MAX is out of unsigned range;
to convert, need to add UINT_MAX. Got UINT_MAX-INT_MAX; it's in the
range so it's the result of conversion. Doesn't compare equal to RHS.
1's complement machine: ~0==-0 ("negative zero"). -0 is in range of
unsigned and the result is 0. Doesn't compare equal to RHS.
All other machines: not recognized by C integer model.

BTW, the picture would be quite different if there was ~0U instead of ~0.
~0U is UINT_MAX and compares equal to RHS.
 
A

Ark Khasin

Please disregard my previous post; obvious corrections are inline in
this one.
 
A

aarklon

(e-mail address removed) writes:




Compiler bug?
i don't thenk there is a compiler bug in it.I compiled the program as
follows:- gcc -ansi -g -o check check.c
"gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5)"
 
P

Philip Potter

Ben said:
No prototype is given for this function, so the compiler cannot
check that the arguments are the correct types.

To prototype a function with no parameters, use void:
void swap(void);

Yes. And I'd add that the declaration
void swap();
specifies that swap() returns void but does not specify the number or
type of arguments. "swap() is a function taking an unspecified, fixed
number of arguments and returning void".

(OT: This declaration means something different in C++, so if you are
familiar with that language it may confuse you.)
It's not necessarily true. But on 2's complement machines, -1 is
represented by all-bits-one.

(unsigned int)-1 is equal to UINT_MAX; this is all-bits-one if UINT_MAX
is of the form (2**n)-1 where n is the number of value bits.

~0 is all-bits-one by definition.

These facts are the same regardless of whether the machine is 2's
complement, 1's complement, or sign-magnitude.

[caveat: by "all-bits-one" I mean "all-value-bits-one"]
Shifting a negative number right invokes undefined behavior,

Not undefined, but implementation-defined. n1256 6.5.7p5:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has
an unsigned type or if E1 has a signed type and a nonnegative value, the
value of the result is the integral part of the quotient of E1 / 2E2. If
E1 has a signed type and a negative value, the resulting value is
implementation-defined.
but
most machines define it to propagate the sign bit to the right.
Since -1 is all-bits-one on your machine, this means that
shifting -1 to the right doesn't change any bits.

Undefined behavior. See the C FAQ, e.g.

Yes. To the OP: what are you trying to do? What do you think

i=i^=j ||i;
will do which
i^=j||i;
won't?

And are you aware that the value (j||i) can only have the value 1 or 0?
Therefore i^=(j||i) will either flip the least-significant bit of i or
it won't change i at all. Why are you doing this?
 
A

Army1987

(unsigned int)-1 is equal to UINT_MAX; this is all-bits-one if UINT_MAX
is of the form (2**n)-1 where n is the number of value bits.

~0 is all-bits-one by definition.

These facts are the same regardless of whether the machine is 2's
complement, 1's complement, or sign-magnitude.
0 is a signed int. ~0 might be a trap, it might be (negative) 0
and it could be -1. In the first case the behavior is undefined,
and in the second case it becomes 0U when converted to unsigned
int.
 
J

James Kuyper

Philip said:
(unsigned int)-1 is equal to UINT_MAX; this is all-bits-one if UINT_MAX
is of the form (2**n)-1 where n is the number of value bits.

.... as is required by the C standard (6.2.6.2p1).

....
~0 is all-bits-one by definition.

These facts are the same regardless of whether the machine is 2's
complement, 1's complement, or sign-magnitude.

[caveat: by "all-bits-one" I mean "all-value-bits-one"]

I believe that the sign bit must be 1 as well.
 
A

aarklon

Not undefined, but implementation-defined. n1256 6.5.7p5:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has
an unsigned type or if E1 has a signed type and a nonnegative value, the
value of the result is the integral part of the quotient of E1 / 2E2. If
E1 has a signed type and a negative value, the resulting value is
implementation-defined.
then what about printf("%d",-1<<3);??
 
J

James Kuyper

then what about printf("%d",-1<<3);??

6.5.7p1: "If E1 has a signed type and nonnegative value, and E1 ´ 2E2 is
representable in the result type, then that is the resulting value;
otherwise, the behavior is undefined."

Do you have a copy of the standard? The actual standard costs a little
money, but you can get n1256.pdf for free, and it's close enough for
most purposes.
 
A

aarklon

(e-mail address removed) wrote:

...


6.5.7p1: "If E1 has a signed type and nonnegative value, and E1 ´ 2E2 is
representable in the result type, then that is the resulting value;
otherwise, the behavior is undefined."

Do you have a copy of the standard? The actual standard costs a little
money, but you can get n1256.pdf for free, and it's close enough for
most purposes.

where to get this n1256.pdf for free ??
 
K

Kenny McCormack

then what about printf("%d",-1<<3);??

I'm surprised and shocked that no one has pointed out the lack of the
newline - which of course makes the whole program invalid (and OT...)
 
K

Kenny McCormack

(e-mail address removed) wrote:
...

6.5.7p1: "If E1 has a signed type and nonnegative value, and E1 ´ 2E2 is
representable in the result type, then that is the resulting value;
otherwise, the behavior is undefined."

Do you have a copy of the standard? The actual standard costs a little
money, but you can get n1256.pdf for free, and it's close enough for
most purposes.

But is that going to be good enough to be able to compete effectively in
the greasepit that is CLC? I.e., if you try to claim something in here
based on what you read in the free version, you run the risk of someone
who has access to the "real" version coming along and smashing you.
 
S

santosh

i don't thenk there is a compiler bug in it.I compiled the program as
follows:- gcc -ansi -g -o check check.c

I also suggest the addition of '-Wall' '-W' and '-pedantic' options.
 
P

Philip Potter

Army1987 said:
0 is a signed int. ~0 might be a trap, it might be (negative) 0
and it could be -1. In the first case the behavior is undefined,
and in the second case it becomes 0U when converted to unsigned
int.

Yes, you're right. I was confusing ~0 with ~0U.

(Another case you didn't mention: ~0 may be INT_MIN, under sign-magnitude.)
 
P

Philip Potter

where to get this n1256.pdf for free ??

I wouldn't recommend learning C from the C standard or from n1256, the C
draft. It's good for checking behaviour, but not for learning the
language. Get a good textbook, such as K&R, instead.
 
J

James Kuyper

Philip said:
I wouldn't recommend learning C from the C standard or from n1256, the C
draft. It's good for checking behaviour, but not for learning the
language. Get a good textbook, such as K&R, instead.

I agree - the standard is a lousy textbook, but a good reference work. I
haven't needed a textbook for C for a couple of decades, so I can't give
any current recommendations along those lines, but the text book I used
several decades ago was K&R, 1st edition, and it was excellent.
 
J

J. J. Farrell

i don't thenk there is a compiler bug in it.

How else do you explain the incorrect output?
I compiled the program as
follows:- gcc -ansi -g -o check check.c
"gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5)"

How is that relevant to whether or not there is a compiler bug?
 
F

Flash Gordon

J. J. Farrell wrote, On 04/11/07 17:28:
How else do you explain the incorrect output?

The incorrect output suggests either a compiler bug or the OP not
posting the actual code used. I tried and gcc produced the correct
results at all optimisation level even without me correcting the program
by including stdio.h
How is that relevant to whether or not there is a compiler bug?

Well, it allows the OP to see if s/he is testing using an older version
of gcc and thus helps in determining whether it is a bug that has been
fixed.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top