role of preprocessor

  • Thread starter Merrill & Michele
  • Start date
M

Merrill & Michele

I know that for my own programs, the things that precede the main call are
either remarks or begin with a hash. What else can you put up there? MPJ
 
E

Eric Sosman

Merrill said:
I know that for my own programs, the things that precede the main call are
either remarks or begin with a hash. What else can you put up there? MPJ

Declarations and definitions of functions, types, and
variables. In short, any (correct) code:

#include <stdio.h>

typedef enum { ENGLISH, LATIN } Language;

static const char *salutation(Language l) {
return (l == ENGLISH) ? "Hello" : "Ave";
}

static const char *divider = ", ";

static const char *planet(Language l) {
return (l == LATIN) ? "Terra" : "World";
}

static const char closing[] = "!\n";

static void printstring(const char *string) {
fputs (string, stdout);
}

int main(int argc, char **argv) {
Language tongue = (argc > 1) ? LATIN : ENGLISH;
printstring(salutation(tongue));
printstring(divider);
printstring(planet(tongue));
printstring(closing);
return 0;
}

(This is, of course, a clumsy program for its task. The
point was to exhibit things that could precede main(), not
necessarily things that *should* precede main(). Note also
that most "significant" C programs have many independently-
compiled source files yet only one main(); it follows that
main() is not a necessary part of every source file.)
 
M

Merrill & Michele

"Eric Sosman" :
Declarations and definitions of functions, types, and
variables. In short, any (correct) code:

#include <stdio.h>

typedef enum { ENGLISH, LATIN } Language;

static const char *salutation(Language l) {
return (l == ENGLISH) ? "Hello" : "Ave";
}

static const char *divider = ", ";

static const char *planet(Language l) {
return (l == LATIN) ? "Terra" : "World";
}

static const char closing[] = "!\n";

static void printstring(const char *string) {
fputs (string, stdout);
}

int main(int argc, char **argv) {
Language tongue = (argc > 1) ? LATIN : ENGLISH;
printstring(salutation(tongue));
printstring(divider);
printstring(planet(tongue));
printstring(closing);
return 0;
}

(This is, of course, a clumsy program for its task. The
point was to exhibit things that could precede main(), not
necessarily things that *should* precede main(). Note also
that most "significant" C programs have many independently-
compiled source files yet only one main(); it follows that
main() is not a necessary part of every source file.)

How about:
int i = 0;
++ i;
int main (){
return 0
}
MPJ

(I can't imagine that that is kosher, but I'm frequently surprised.)
 
J

Joona I Palaste

Merrill & Michele said:
How about:
int i = 0;
++ i;
int main (){
return 0
}
MPJ
(I can't imagine that that is kosher, but I'm frequently surprised.)

This should not even compile. You cannot put executable statements
outside functions.
 
E

Eric Sosman

Merrill said:
Merrill & Michele wrote:
I know that for my own programs, the things that precede the main call
are
either remarks or begin with a hash. What else can you put up there?

"Eric Sosman" :
Declarations and definitions of functions, types, and
variables. In short, any (correct) code:
[...]

How about:
int i = 0;

Fine: this is a variable definition, with an
initializer.

Not fine: this is an executable statement, and an
executable statement can exist only inside the body of a
function definition. It cannot "stand alone."
int main (){
return 0

Not fine: a semicolon is required.
}
MPJ

(I can't imagine that that is kosher, but I'm frequently surprised.)

Examine my list of possibilities again: You can have
(1) declarations and (2) definitions of (A) functions,
(B) types, and (C) variables. That's six combinations:

1A: Function declarations
int foo(double);
void bar(long time_no_see);

1B: Type declarations
struct this { double toil; double trouble; };
union jack { char coal[128]; long john_silver; };
enum fruit { APPLE, BANANA, CRANBERRY };

1C: Variable declarations
extern struct this global_that;
extern double global_trouble;

2A: Function definitions
int foo(double x) { return x > 0.0; }
void bar(long time_no_see) {
printf ("%ld\n", time_no_see);
}

2B: Type definitions
(Well, I lied: You can't really "define" a type.
Chalk it up to a failed attempt at brevity.)

2C: Variable definitions
static double electricity;
char *situation = "hopeless";
enum fruit peelable_fruits[] = {
APPLE, BANANA };

Now, to ward off my fellow pedants let me emphasize
that there are several things wrong with this list. The
main thing is that every definition also serves as a
declaration, so the nice, neat "1 or 2" categorization
above isn't quite right. Also, the Standard talks about
something called a "tentative definition," which is really
just a formalization of how the information about a single
data object can be gathered from several bits of source.
Judging from some of the questions you've asked I suspect
that a thorough study of such subtleties would do more harm
than good at this point; return to the matter once your
grasp of the structure of C programs is firmer.
 
T

Thomas Stegen

Merrill said:
How about:
int i = 0;

This you can do. Though you may have heard that global variables
should be viewed with suspicion. Sometimes they are the best
solution to your problem, but most often they are to be avoided.

This you can not do.
 
M

Merrill & Michele

MPJ:
[outside of a function]
Thomas Stegen et ali:
This you can not do.

Thanks all for replies, in particular Mr. Sosman with his generous detail.
Ever since I was made aware of K&R2 ex 1-24, I've been thinking about how
I'd do it. Of course, if I solved the problem completely, I would have
something darn near a compiler.
 

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,150
Messages
2,570,853
Members
47,394
Latest member
Olekdev

Latest Threads

Top