output from program - why?

A

Allan M. Bruce

I just recently took a C programming test (which was a total farce - but
thats not the point). The code below is a combination of two questions that
were included in the test and I was hoping to raise a few questions about
it. First, the code:

#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int increment(int *in)
{
(*in)++;
/* *in++; */ /* Doesnt work*/
return *in;
}

int main(void)
{
int i=1;
printf("%s %s\n", g(f((1,2),3)), h(f((1,2),3)));
printf("%i%i\n", increment(&i), increment(&i));
return 0;
}


The output from the above is:
f((1,2),3) (1,2)3
32

I have 3 questions...

1) Why is the output of the first line so? I have never come across # in
defines.

2) What is the difference between (*in)++ and *in++ ? obviously the latter
doesnt work as I have tested it. Is this because the ++ has higher priority
over *?

3) The output from the last printf is 32, which I suspect because the
variable arguements to printf are executed in reverse order, is this
correct?

Many Thanks
Allan
 
B

Bart Rider

Allan said:
I just recently took a C programming test (which was a total farce - but
thats not the point). The code below is a combination of two questions that
were included in the test and I was hoping to raise a few questions about
it. First, the code:

#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int increment(int *in)
{
(*in)++;
/* *in++; */ /* Doesnt work*/
return *in;
}

int main(void)
{
int i=1;
printf("%s %s\n", g(f((1,2),3)), h(f((1,2),3)));
printf("%i%i\n", increment(&i), increment(&i));
return 0;
}


The output from the above is:
f((1,2),3) (1,2)3
32
[...skip...]

3) The output from the last printf is 32, which I suspect because the
variable arguements to printf are executed in reverse order, is this
correct?

In my xterm the output is
f((1,2),3) (1,2)3
23
I used the gcc compiler 3.1 to compile your program.
It seems, that the order of executing arguments is
compiler dependent.
 
H

Haider

1) for first line ## operator is for concatenating two string so when
you call function f(a,b) it will give u result "ab"
#define g(a) #a
when you call g(xyz) it give you result xyz now i think you can make
the output of first line.

2) (*in)++ increments whatever 'in' points to but *in++ first
increment the pointer i.e. increment the address then access the
content. it is due to associativity of ++ operator which is left to
right.

3)it depnds on compiler to compiler on some compiler it will give 23.
in C there is no fix rule.
 
F

Flash Gordon

That is because *in++ is equivalent to *(in++). This should be covered
in the precedence table of whatever text book you are using.
In my xterm the output is
f((1,2),3) (1,2)3
23
I used the gcc compiler 3.1 to compile your program.
It seems, that the order of executing arguments is
compiler dependent.

The order of execution is unspecified, which means it can vary not only
from compiler to compiler, but even on consecutive runs of the program.
So you should not write code like that shown.

This is in the comp.lang.c FAQ http://c-faq.com/ specifically question
3.7. The FAQ should be consulted prior to posting.
 
B

Bob

The output from the above is:
f((1,2),3) (1,2)3
32

I have 3 questions...

1) Why is the output of the first line so? I have never come across # in
defines.

This one is tricky. Note that the output of the first string in the
printf expression is stripped of the g but not the f. But the second
argument is stripped of both h and f.

The # in a define is a # operator or a "stringization" operator, if
you will. The argument and the preceding # is replaced by a string
whose content is the argument. It stops further macro expansion since
macros are not searched for in strings.

The ## operator allows concatenation of two adjacent 'tokens' into
one.

g is a function-like macro that replaces its argument by a
string-form. So the macro substitution sequence is something like
this (please forgive typos):

printf("%s %s\n", g(f((1,2),3)), h(f((1,2),3)));

printf("%s %s\n", "f((1,2),3)",g(f((1,2),3)));
/* The third argument is now a string. */

printf("%s %s\n", "f((1,2),3)",g((1,2),3));
/* The fourth argument was concatenated by f's expansion. */

printf("%s %s\n", "f((1,2),3)","(1,2),3)";


Prints 'f((1,2),3) (1,2)3'.

2) What is the difference between (*in)++ and *in++ ? obviously the latter
doesnt work as I have tested it. Is this because the ++ has higher priority
over *?

Yes, *in++ increments the pointer 'in' first, then dereferences the
value. It is a precedence issue.
3) The output from the last printf is 32, which I suspect because the
variable arguements to printf are executed in reverse order, is this
correct?

The order of evaluation of arguments in functions is implementation
defined. My implementation actually gives 23.

It is a poorly designed program that depends upon implementation
defined behavior. You get 32 and I get 23 from the same program! It
would drive people crazy, at least me :) .

Hence, do not depend upon the order of evaluation of function
arguments.

Best wishes,

Bob
 
T

Thad Smith

Allan said:
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int increment(int *in)
{
(*in)++;
/* *in++; */ /* Doesnt work*/
return *in;
}

int main(void)
{
int i=1;
printf("%s %s\n", g(f((1,2),3)), h(f((1,2),3)));
printf("%i%i\n", increment(&i), increment(&i));
return 0;
}


The output from the above is:
f((1,2),3) (1,2)3
32

I have 3 questions...

1) Why is the output of the first line so? I have never come across # in
defines.

If you want to learn C, you should find an appropriate text which covers
the full preprocessor. It is included in the Standard, of course, but
that is harder to read.

The expression h(f((1,2),3)) results in undefined behavior. The results
of the preprocessing concatenation operator is only defined if the
results is a preprocessing token. That is not true in this case.
> 3) The output from the last printf is 32, which I suspect because the
> variable arguements to printf are executed in reverse order, is this
> correct?

The second printf statement invokes increment() twice. Increment
modifies the value of i. The Standard does not specify the order in
which arguments are evaluated, so the output order of the two values is
unspecified.
 
A

Allan M. Bruce

Bob said:
This one is tricky. Note that the output of the first string in the
printf expression is stripped of the g but not the f. But the second
argument is stripped of both h and f.

The # in a define is a # operator or a "stringization" operator, if
you will. The argument and the preceding # is replaced by a string
whose content is the argument. It stops further macro expansion since
macros are not searched for in strings.

The ## operator allows concatenation of two adjacent 'tokens' into
one.

g is a function-like macro that replaces its argument by a
string-form. So the macro substitution sequence is something like
this (please forgive typos):

printf("%s %s\n", g(f((1,2),3)), h(f((1,2),3)));

printf("%s %s\n", "f((1,2),3)",g(f((1,2),3)));
/* The third argument is now a string. */

printf("%s %s\n", "f((1,2),3)",g((1,2),3));
/* The fourth argument was concatenated by f's expansion. */

printf("%s %s\n", "f((1,2),3)","(1,2),3)";


Prints 'f((1,2),3) (1,2)3'.



Yes, *in++ increments the pointer 'in' first, then dereferences the
value. It is a precedence issue.


The order of evaluation of arguments in functions is implementation
defined. My implementation actually gives 23.

It is a poorly designed program that depends upon implementation
defined behavior. You get 32 and I get 23 from the same program! It
would drive people crazy, at least me :) .

Hence, do not depend upon the order of evaluation of function
arguments.

Best wishes,

Bob

Thanks for the helpful response
Allan
 

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

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,216
Latest member
topweb3twitterchannels

Latest Threads

Top