Your opinion

D

Dan Pop

In said:
Ok, I get the point. But if you were asked this question in a
technical test with 4 options

a) error during compilation
b) goes into an infinite loop
c) 5 6.000000 6 5.000000
d) 5 6.000000 0 0.000000

What would you choose?

It depends on the date the question was asked ;-)

Before the release of C89, the answer would be a) or b): the macro
replacement causes infinite recursion, which could result in either an
error message or the preprocessor going into an infinite loop:

mentor:~/tmp 12> gcc -traditional -E test.c
test.c:6: macro or `#include' recursion too deep
test.c:7: macro or `#include' recursion too deep
test.c:8: macro or `#include' recursion too deep
test.c:8: macro or `#include' recursion too deep
test.c:9: macro or `#include' recursion too deep
test.c:9: macro or `#include' recursion too deep
# 1 "test.c"



main()
{
int =5;
float =6.0;
printf("\n %d %f",,);
printf(" %d %f",,);
}

In standard C, the macro definitions are harmless, the nested macro
replacement being stopped when the original macro name comes up again,
so by the time A becomes A again, the replacement is stopped. But,
in standard C, calling printf without a prototype in scope and passing
an argument of the wrong type to printf results in undefined behaviour,
which includes *all* the above listed options, as well as an infinity
of others.

And a C99 compiler would also object to the definition of the main
function, which requires an explicit return type.

However, the program has the look and feel of a pre-ANSI C program...

Dan
 
B

Ben Pfaff

Why does this perform no operation? What am I missing?

I thought the following:

#define A B
#define B A

worked by first replacing all As' with Bs' then all Bs' with As' but
that is not how this works. Why is this?

`A' gets expanded to `B', which gets expanded to `A'. At that
point, the preprocessor stops expanding because it has already
expanded `A'; it will not expand a macro from within its own
expansion. The explanation for `B' is similar.
 
R

Ravi

Why does this perform no operation? What am I missing?

#define A B
#define B A


int main(void)
{
B;
return 1;
}

on compiling:
Error 7: Undefined symbol 'B'


_____________

//#define A B
#define B A


int main(void)
{
B;
return 1;
}

On compiling:
Error 7: Undefined symbol 'A'

This might make thing clear :)
 
D

Dan Pop

In said:
#define A B
#define B A


int main(void)
{
B;
return 1;
}

on compiling:
Error 7: Undefined symbol 'B'


_____________

//#define A B
#define B A


int main(void)
{
B;
return 1;
}

On compiling:
Error 7: Undefined symbol 'A'

This might make thing clear :)

Do yourself a favour and learn how to obtain the preprocessor's output:
it's much easier to solve preprocessing issues this way than by
examining compiler error messages.

Dan
 
R

Ravi

Is it?


C99 7.1.3 Reserved identifiers:

- Each identifier with file scope listed in any of the following
subclauses (including the future library directions) is
reserved for use as a macro name and as an identifier with
^^^^^^^^^^^^^^^
file scope in the same name space if any of its associated
headers is included.

OTOH, even a C89 implementation can define the macro scanf if
<stdio.h> is included, so, the code, with your suggested fixes, may not
work there, either.

Then, we have the issue of the last line of output not being newline
terminated...

The proper way of fixing the code is:

#define scanf "%s is a string"
int printf(const char *format, ...);
int putchar(int);

int main()
{
printf(scanf, scanf);
putchar('\n');
return 0;
}

The true pedant would also attempt to fix the "restrict" issue in the
printf prototype ;-)

But if we replace scanf with MACDEF will the code be acceptable?
 
R

Ravi

Do yourself a favour and learn how to obtain the preprocessor's output:
it's much easier to solve preprocessing issues this way than by
examining compiler error messages.

How would I do that on Turbo C++?

Thank a lot for helping :)
 
R

Ravi

How would I do that on Turbo C++?

Thank a lot for helping :)

Or you can also tell me how it can be done on a Linux machine with all
standard development tools installed.
 
A

Andreas Kahari

[cut]
Or you can also tell me how it can be done on a Linux machine with all
standard development tools installed.

On all systems with the GNU Compiler Collection (GCC) installed
(almost any popular OS I can think of can run GCC):

gcc -E file.c

You've got TFM, now R it.
 
R

Ravi

On all systems with the GNU Compiler Collection (GCC) installed
(almost any popular OS I can think of can run GCC):

gcc -E file.c

You've got TFM, now R it.

Thanks for the kind reply.
 
R

Ravi

Thanks for the kind reply.

$ cat temp.c
#define A B
#define B A
#define A 5
main()
{
printf("\n %d %f",A,B);
printf(" %d %f",B,A);
}

$ gcc -E temp.c
# 4 "temp.c"
main()
{
printf("\n %d %f",5,5);
printf(" %d %f",5,5);
}

If someone could help me understand this...

TIA.
 
B

Ben Pfaff

Ravi said:
$ gcc -E temp.c
# 4 "temp.c"
main()
{
printf("\n %d %f",5,5);
printf(" %d %f",5,5);
}

If someone could help me understand this...

Please ask questions about your compiler in a newsgroup about
your compiler.
 
A

Alex

M

Micah Cowan

Ravi said:
But if we replace scanf with MACDEF will the code be acceptable?

Yes (again, assuming <stdlib.h> was #included or appropriate
prototypes are in place). But in C99, the "restrict" issue Dan Pop
refers to would still be an issue, resulting in potential undefined
behavior.

(To readers who may not have caught the "restrict" issue): The problem
is that identical string literals are not required to be unique: the
string literal by which MACDEF would be replaced might be stored in
the very same memory location for both. In C99, printf()'s format
string argument is declared with the "restrict" specifier, which means
essentially that you promise not to pass it another pointer into the
same object. That promise would be violated by the above code (not to
mention that the printf() protype Dan stuck in there wouldn't be valid
anymore, either, as it lacks the "restrict" specifier).

-Micah
 
M

Micah Cowan

Ravi said:
$ cat temp.c
#define A B
#define B A
#define A 5

At this point, any behavior we discuss is off-topic, as you now have
undefined behavior by #defining the same symbol twice with different
replacement lists. However...
main()
{
printf("\n %d %f",A,B);
printf(" %d %f",B,A);
}

$ gcc -E temp.c
# 4 "temp.c"
main()
{
printf("\n %d %f",5,5);
printf(" %d %f",5,5);
}

If someone could help me understand this...

What's to understand? A and B have been replaced by their replacement
lists (which happens to be 5 for both of them). As to why it's 5, no
one can answer that, since it was undefined behavior to begin with. If
you're wondering about the first line, that's not C, it's special
symbols the preprocessor sends to hte compiler to tell it where the
rest of the code came from (since it snipped some lines which were
preprocessor directives).

-Micah
 
A

Arthur J. O'Dwyer

Yes (again, assuming <stdlib.h> was #included or appropriate
prototypes are in place). But in C99, the "restrict" issue Dan Pop
refers to would still be an issue, resulting in potential undefined
behavior.

(To readers who may not have caught the "restrict" issue): The problem
is that identical string literals are not required to be unique: the
string literal by which MACDEF would be replaced might be stored in
the very same memory location for both. In C99, printf()'s format
string argument is declared with the "restrict" specifier, which means
essentially that you promise not to pass it another pointer into the
same object. That promise would be violated by the above code (not to
mention that the printf() protype Dan stuck in there wouldn't be valid
anymore, either, as it lacks the "restrict" specifier).


Wait... so does standard C99 really make it unspecified whether

char *mystring = "%s";
printf("%s", mystring);

invokes undefined behavior? Pardon me, but that's just crazy.
I don't immediately see how to fix it, other than mandating
that each compiler make sure for themselves that string literals
don't interfere with any 'restrict' issues.

-Arthur,
learning something horribly new every day
 
K

Keith Thompson

[...]
#define A B
#define B A

main()
{
int A=5;
float B=6.0;
printf("\n %d %f",A,B);
printf(" %d %f",B,A);
}

Q: What does this program do?

A: It gets re-written.
 
B

Ben Pfaff

Arthur J. O'Dwyer said:
Wait... so does standard C99 really make it unspecified whether

char *mystring = "%s";
printf("%s", mystring);

invokes undefined behavior? Pardon me, but that's just crazy.
I don't immediately see how to fix it, other than mandating
that each compiler make sure for themselves that string literals
don't interfere with any 'restrict' issues.

I don't think that this code is undefined in C99. Check out
example 3 in C99 6.7.3.1:

10 EXAMPLE 3 The function parameter declarations
void h(int n, int * restrict p, int * restrict q, int * restrict r)
{
int i;
for (i = 0; i < n; i++)
p = q + r;
}
illustrate how an unmodified object can be aliased through two restricted pointers. In particular, if a and b
are disjoint arrays, a call of the form h(100, a, b, b) has defined behavior, because array b is not
modified within function h.

printf() doesn't modify its arguments[1] so I don't think that
printf("%s", "%s"); is undefined.

Or am I missing something?

[1] Well, certainly not in this case, unless you want to argue
that one should not pass string literals to printf().
 
B

Bigdakine

Subject: Re: Your opinion
From: Ben Pfaff (e-mail address removed)
Date: 9/22/03 7:01 PM Hawaiian Standard Time
Message-id: <[email protected]>




No, it doesn't. Try a C preprocessor. The macros are no-ops.


You're absolutely right. My mistake.

Stuart
 
B

Bigdakine

Subject: Re: Your opinion
From: Ravi (e-mail address removed)
Date: 9/23/03 7:04 AM Hawaiian Standard Time
Message-id: <[email protected]>



#define A B
#define B A


int main(void)
{
B;
return 1;
}

on compiling:
Error 7: Undefined symbol 'B'


_____________

//#define A B
#define B A


int main(void)
{
B;
return 1;
}

On compiling:
Error 7: Undefined symbol 'A'

This might make thing clear :)


Actually no. THis has nothing to do with the macros. In your code " B ;"
doesn't make sense. B has no type and is hence undefined. So when it is
replaced by A, it is still undefined.

My mistake was in thinking that the preprocessor didn't make recursive
substitutions.

Course, I wouldn't try that example in real life.

Stuart
Dr. Stuart A. Weinstein
Ewa Beach Institute of Tectonics
"To err is human, but to really foul things up
requires a creationist"
 

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
474,083
Messages
2,570,591
Members
47,212
Latest member
RobynWiley

Latest Threads

Top