#define SIG_ERR (void (*) ())-1
#define SIG_DFL (void (*) ())0
#define SIG_IGN (void (*) ())1
Are they the CPP's way of defining a function pointer (cuz SIG_ERR is
a func ptr)?
How to understand this syntax?
Can anyone guide me through this?
Thank you!
--
comp.lang.c.moderated - moderation address: cl...@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
the macros are integers cast to the type "pointer to function returning void".
> How to understand this syntax?
> Can anyone guide me through this?
>
> Thank you!
--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---
I found that this link explains the thing clearly:
http://www.digi-cron.com/programmations/c/lectures/4-signals.html
Regards,
Jyoti
signal() expects a pointer to a function that takes no arguments and
returns no value. These macros cast "flag values" to the correct type
so they can be passed to signal() without causing a compiler warning or
error.
Note that SIG_ERR is only used as a return value; you're not supposed to
pass it to signal().
This would be considered bad style today. If one were to redesign the
signal-handling API today, one would have separate functions for
ignoring or resetting a signal.
Oh, wait, somebody *did* redesign the signal-handling API (sigaction()
in POSIX) and used the exact same trick...
DES
--
Dag-Erling Smørgrav - d...@des.no
I should amend that - C still does not have "implicit void", so these
are pointers to functions that take an indeterminate number of
arguments and return no values.
The following will compile, but invokes undefined behavior:
#include <stdio.h>
void foo(int i) { printf("%d\n", i); }
void (*bar)() = foo;
int main(void) { bar(3, 2, 1); return (0); }
but if you write "foo" instead of "bar" in main(), you should get a
compile-time error.
(I still can't get the diagnostic / constraint violation / etc. thing
straight...)
No, signal() expects a pointer to a function that takes an int
argument and returns no value. The macro definitions above refer to a
function that takes an unspecified but fixed number and type of
arguments.
[...]
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
r...@zedat.fu-berlin.de (Stefan Ram) writes:
> Joey Wang <yal...@gmail.com> writes in comp.lang.c.moderated:
>>I have a problem understanding the following definitions in <signal.h>
>>#define SIG_ERR (void (*) ())-1
>>#define SIG_DFL (void (*) ())0
>>#define SIG_IGN (void (*) ())1
>>Are they the CPP's way of defining a function pointer (cuz SIG_ERR is
>>a func ptr)?
>>How to understand this syntax?
>>Can anyone guide me through this?
>
> The header files provided by an implementation are not
> bounded by the limits of portable C code, but free to use
> implementation-specified notations. A user of a
> C implementations is not supposed to understand his
> implementation's header files nor to modify them.
>
> #define usually just does text substitutions.
> The preprocessor usually is not aware of the structure of the
> C language proper. But an implementation possibly might even
> be free to change the meaning of #define for its own header
> files or standard macro names (although I never heard of this).
All true, but not entirely relevant to the question.
First of all, the OP omitted some parentheses. The actual definitions
are probably:
#define SIG_ERR ((void (*) ())-1)
#define SIG_DFL ((void (*) ())0)
#define SIG_IGN ((void (*) ())1)
Each definition is an integer constant expression converted,
via a cast, to a pointer-to-function type. The cast is to type
``void(*)()'', i.e., pointer to function returning void.
A modern implementation would probably define the
parameter type:
#define SIG_ERR ((void (*) (int))-1)
#define SIG_DFL ((void (*) (int))0)
#define SIG_IGN ((void (*) (int))1)
SIG_ERR, SIG_DFL, and SIG_IGN have to be function pointers, but
they merely have to be unique values; it needn't be possible to
call anything using their values. Converting a constant 0 to a
pointer-to-function type yields a null pointer, so SIG_DFL happens
to expand to an expression that evaluates to a null pointer value;
(SIG_DFL == NULL) is true. Converting any other integer value to
a pointer-to-function type yields some value that's not specified
by the standard (I'm not sure whether it's implementation-defined
or unspecified). The point is that, for the implementation for
which the above definitions were written, the three expressions
yield pointer values that are distinguishable from any pointer to
an actual function.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Why? The non-parenthesized versions are perfectly valid and will work
in most cases, including those cases in which they are actually intended
to be used.
DES
--
Dag-Erling Smørgrav - d...@des.no
C99 7.1.2p5:
Any definition of an object-like macro described in this clause
shall expand to code that is fully protected by parentheses
where necessary, so that it groups in an arbitrary expression
as if it were a single identifier.
Even without that explicit requirement, there would be no good reason
*not* to fully parenthesize the definitions. It's not likely that
someone would write
sizeof SIG_ERR
but why not let it yield the correct result?
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
One reason for using parenthesis here is to prevent incorrect parsing of
expressions that would be perfectly legitimate with the parenthesis. It
happens to be the case that, for these particular macros, there are no
such expressions; every expression where the parenthesis would change
the parsing is an inappropriate use of these macros.
The second reason is to prevent incorrect parsing of invalid uses of the
macros, uses that would otherwise be syntax errors or constraint
violations, with the result that desirable diagnostic messages get
turned off. For instance, SIG_IGN["abcde"] is a syntax error with the
parenthesis, but without them it is not: it's equivalent to
(void(*)())'b'. I will grant you that subscripting with a pointer type
is the only such case I could come up with, and is an extremely unlikely
one.
The point is, while it can be shown for these particular macros that the
benefit of the parenthesis provide negligible benefit, it takes an
expert knowledge of the language, and careful thought, to be certain
that the benefit is negligible. That expertise and thought would have
been better spent on some other task. Keep in mind that the next person
who reads that code might lack either the expertise or the time needed
to apply it - writing such code causes problems for them, and not just
for the author. You should simply make a habit of normally
parenthesizing macros that define expressions (and also all uses of the
arguments of function-like macros).
You missed something.
Given
#define SIG_ERR (void (*) ())-1
``sizeof SIG_ERR'' expands to ``sizeof (void (*) ())-1''. The unary
minus becomes a subtraction operator, and the result is the size of
the pointer-to-function type minus 1.
And as I mentioned in a parallel followup, the standard explicitly
requires the parentheses.
[...]
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
See my reply to James Kuyper; I agree that parens are good, but I don't
think the OP removed them. I think they weren't there to begin with.
DES
--
Dag-Erling Smørgrav - d...@des.no
I know that perfectly well. I just disagree with Keith's assumption
that the OP had removed the parentheses, not least because the point of
the thread was that the OP did not understand what the macros did.
DES
--
Dag-Erling Smørgrav - d...@des.no
If so, he copied the definitions from a non-conforming
implementation. (Possibly it was non-conforming because it was
very old.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"