What's this in C?

Z

zhangyue.zl

static void (DEVICE_REQUEST)(void);

What does this line declare in C?
I am always meeting some codes like this,but I have never learnt that
before.
It looks like a declaration of a function,but why DEVICE_REQUEST has to
be quoted by ( ).
Anyone can explain that to me? thanks a lot!
 
V

Vladimir S. Oka

static void (DEVICE_REQUEST)(void);

What does this line declare in C?
I am always meeting some codes like this,but I have never learnt that
before.
It looks like a declaration of a function,but why DEVICE_REQUEST has to
be quoted by ( ).
Anyone can explain that to me? thanks a lot!

Well, it would have helped a lot if you showed what DEVICE_REQUEST is.

One reason it might be in parentheses is if it's #defined as:

#define DEVICE_REQUEST *some_name

Parenthese then make sure your original line declares `some_name` as a
pointer to a function which takes no parameters and returns void
(nothing):

static void (*some_name)(void);

It is not a declaration of a function, but a pointer you can use to
call a function.

Is this the answer you were looking for? If not, let us know what
DEVICE_REQUEST is.
 
R

Richard Heathfield

(e-mail address removed) said:
static void (DEVICE_REQUEST)(void);

What does this line declare in C?

A function called DEVICE_REQUEST, which takes no parameters and returns no
value, and which has internal linkage.
I am always meeting some codes like this,but I have never learnt that
before.
It looks like a declaration of a function,but why DEVICE_REQUEST has to
be quoted by ( ).

If some clown has done

#define DEVICE_REQUEST(x) someexpressioninvolving x

the parentheses stop the preprocessor from performing the usual
substitution. The definition and call would have to be similarly
parenthesised:

void (DEVICE_REQUEST)(void)
{
;
}

int main(void)
{
(DEVICE_REQUEST)();
return 0;
}
 
T

Thad Smith

static void (DEVICE_REQUEST)(void);

What does this line declare in C?
I am always meeting some codes like this,but I have never learnt that
before.
It looks like a declaration of a function,but why DEVICE_REQUEST has to
be quoted by ( ).

It is. The parentheses are optional, but if a function-like macro named
DEVICE_REQUEST is defined, the parentheses prevent macro substitution.
 
R

Rod Pemberton

static void (DEVICE_REQUEST)(void);

What does this line declare in C?
I am always meeting some codes like this,but I have never learnt that
before.
It looks like a declaration of a function,but why DEVICE_REQUEST has to
be quoted by ( ).
Anyone can explain that to me? thanks a lot!

Yes. It prevents DEVICE_REQUEST from being redefined by a macro. This is
frequently done in system libraries.

Rod Pemberton
 
K

Keith Thompson

Rod Pemberton said:
Yes. It prevents DEVICE_REQUEST from being redefined by a macro. This is
frequently done in system libraries.

It prevents any definition of DEVICE_REQUEST as a function-like macro
from being expanded at that point. If DEVICE_REQUEST is an
object-like macro, it will still be expanded. You're probably right
about the intent in this case, but it's impossible to tell without
seeing how and whether DEVICE_REQUEST is defined.

(If DEVICE_REQUEST *isn't* a macro, naming it in all-caps is probably
poor style.)
 
B

Ben Pfaff

Rod Pemberton said:
It prevents DEVICE_REQUEST from being redefined by a macro.

This could be better phrased. In fact, it doesn't prevent any
such definition, it just prevents the function-like macro named
DEVICE_REQUEST, if any, from being expanded at that point in the
code. (If DEVICE_REQUEST is the name of a macro that does not
take arguments, it will still be expanded.)
 
R

Rod Pemberton

Keith Thompson said:
It prevents any definition of DEVICE_REQUEST as a function-like macro
from being expanded at that point. If DEVICE_REQUEST is an
object-like macro, it will still be expanded. You're probably right
about the intent in this case, but it's impossible to tell without
seeing how and whether DEVICE_REQUEST is defined.

You, Ben and Thad, make a distinction between a "function-like macro" and an
"object-like macro."

P.J. Plauger's exact wording on how this works (or is supposed to work):
"In the definition of a visible library function, the function name is
surrounded by parenthesis. ... Any such function can have its declaration
masked by a macro definition in its corresponding header. The parenthesis
prevent the translator from recognizing the macro and expanding it."

He makes no distinction between the two as far as I can tell. So, where
exactly do you get this?


Rod Pemberton
 
K

Keith Thompson

Rod Pemberton said:
You, Ben and Thad, make a distinction between a "function-like macro" and an
"object-like macro."

P.J. Plauger's exact wording on how this works (or is supposed to work):
"In the definition of a visible library function, the function name is
surrounded by parenthesis. ... Any such function can have its declaration
masked by a macro definition in its corresponding header. The parenthesis
prevent the translator from recognizing the macro and expanding it."

He makes no distinction between the two as far as I can tell. So, where
exactly do you get this?

C99 6.10.3.
 
Z

zhangyue.zl

Thanks everyone!
I also found these codes:
#define DEVICE_REQUEST do_hd_request

and do_hd_request is a function like this:
void do_hd_request(void)
{
...........
}
 
Z

zhangyue.zl

Thanks everyone!
I also found these codes:
#define DEVICE_REQUEST do_hd_request

and do_hd_request is a function like this:
void do_hd_request(void)
{
...........
}
 
J

Jack Klein

You, Ben and Thad, make a distinction between a "function-like macro" and an
"object-like macro."

P.J. Plauger's exact wording on how this works (or is supposed to work):
"In the definition of a visible library function, the function name is
surrounded by parenthesis. ... Any such function can have its declaration
masked by a macro definition in its corresponding header. The parenthesis
prevent the translator from recognizing the macro and expanding it."

He makes no distinction between the two as far as I can tell. So, where
exactly do you get this?

Doesn't it seem clear to you that the statement you quoted above is
specifically about function names?

Somebody else cited a reference from C99, but it has to do with the
distinction between "ordinary" and "function-like" macros.

Ordinary macros are simple text replacement where the macro itself is
replaced by the specified text. This happens everywhere except in a
few specific contexts, such as inside a comment or quoted string, when
used with the "stringizing" preprocessor operator, or when it appears
recursively in its own expansion. Nothing other than the macro
identifier itself it replaced.

In function-like macros, the macro identifier itself is likely to be
replaced, but also parenthesized arguments that follow it. In other
words, the macro actually defines multiple identifiers that are
replaced on expansion.

Example:

#define SHOW_ERROR(err) fprintf(stderr, "Error = %d\n", (err))

Here the SHOW_ERROR macro not only generates replacement text for
itself when expanded, it also replaces the parameter 'err' with the
macro argument.

The C grammar for defining this type of macro requires that the
opening '(' be the first preprocessor token after the macro
identifier, meaning there can be nothing but white space characters in
between.

The requirement for the preprocessor to expand this macro is similar,
namely that the '(' preprocessor token immediately follow the macro
identifier. Putting the macro identifier in parentheses places a ')'
preprocessor token between the identifier and the '('.

Try it and see.

Also try:

#define X_PLUS_3 x + 3

#include <stdio.h>

int main(void)
{
int x = 0;
printf("%d\n", X_PLUS_3);
x = 10;
printf("%d\n", (X_PLUS_3));
return 0;
}

....and see what the parentheses do there.
 
B

Ben Pfaff

Rod Pemberton said:
P.J. Plauger's exact wording on how this works (or is supposed to work):
"In the definition of a visible library function, the function name is
surrounded by parenthesis. ... Any such function can have its declaration
masked by a macro definition in its corresponding header. The parenthesis
prevent the translator from recognizing the macro and expanding it."

He makes no distinction between the two as far as I can tell. So, where
exactly do you get this?

The standard actually says something similar, in C99 7.1.4:

Any macro definition of a function can be suppressed locally
by enclosing the name of the function in parentheses,
because the name is then not followed by the left
parenthesis that indicates expansion of a macro function
name.

Clearly, an object-like macro definition can't be suppressed the
same way.
 
K

Keith Thompson

Ben Pfaff said:
The standard actually says something similar, in C99 7.1.4:

Any macro definition of a function can be suppressed locally
by enclosing the name of the function in parentheses,
because the name is then not followed by the left
parenthesis that indicates expansion of a macro function
name.

Clearly, an object-like macro definition can't be suppressed the
same way.

Yes, but the context makes it clear that it refers only to the
function-like macro definitions that are allowed by the standard:

Any function declared in a header may be additionally implemented
as a function-like macro defined in the header, so if a library
function is declared explicitly when its header is included, one
of the techniques shown below can be used to ensure the
declaration is not affected by such a macro. Any macro definition
of a function can be suppressed locally by enclosing the name of
the function in parentheses, because the name is then not followed
by the left parenthesis that indicates expansion of a macro
function name. For the same syntactic reason, it is permitted to
take the address of a library function even if it is also defined
as a macro.

I don't think an implementation is allowed to provide an object-like
macro for a library function (at least not in a way that makes any
difference).
 
B

Ben Pfaff

[quoting rearranged to suit the way I meant my text to be
interpreted, see below]
Yes, but the context makes it clear that it refers only to the
function-like macro definitions that are allowed by the standard:

I am certain that text elsewhere in the standard adds up to what
the sentence quoted states. In other words, if that sentence
wasn't in the standard, or if it appeared only in a footnote, it
would still be true.

Thus, I don't see how the context matters.
I don't think an implementation is allowed to provide an object-like
macro for a library function (at least not in a way that makes any
difference).

Agreed.
 
R

Rod Pemberton

Jack Klein said:
Doesn't it seem clear to you that the statement you quoted above is
specifically about function names?

Plauger's statement doesn't say the same thing (to me) as C99 7.1.4. Given
situation A) and B) below, my understanding, from Plauger, was that
"DEVICE_REQUEST" wouldn't be expanded or replaced as "do_hd_request" in
either case. C99 7.1.4 makes it clear that only case A) is unexpanded.

/* case A) parameterized or function-like macro */
#define DEVICE_REQUEST(x) do_hd_request(x)
void (DEVICE_REQUEST)(void);

/* case B) non-parameterized or object-like macro */
#define DEVICE_REQUEST do_hd_request
void (DEVICE_REQUEST)(void);



Rod Pemberton
 
D

Dave Thompson

In function-like macros, the macro identifier itself is likely to be
replaced, but also parenthesized arguments that follow it. In other
words, the macro actually defines multiple identifiers that are
replaced on expansion.

Example:

#define SHOW_ERROR(err) fprintf(stderr, "Error = %d\n", (err))

Here the SHOW_ERROR macro not only generates replacement text for
itself when expanded, it also replaces the parameter 'err' with the
macro argument.

The C grammar for defining this type of macro requires that the
opening '(' be the first preprocessor token after the macro
identifier, meaning there can be nothing but white space characters in
between.
No whitespace. #define FOO (bar) xyz
is an object-like macro that expands to (bar) xyz .
The requirement for the preprocessor to expand this macro is similar,
namely that the '(' preprocessor token immediately follow the macro
identifier. Putting the macro identifier in parentheses places a ')'
preprocessor token between the identifier and the '('.
Right.

Try it and see.

Also try:

#define X_PLUS_3 x + 3

#include <stdio.h>

int main(void)
{
int x = 0;
printf("%d\n", X_PLUS_3);
x = 10;
printf("%d\n", (X_PLUS_3));
return 0;
}

...and see what the parentheses do there.

Huh? In this case, they don't do anything.

- David.Thompson1 at worldnet.att.net
 

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,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top