1

Here's the definition of macros defined in signal.h according to ISO C N2176_C17_finaldraft document 7.14.3:

The Macros defined are:

SIG_DFL
SIG_ERR
SIG_IGN

which expand to constant expressions with distinct values that have type compatible with the second argument to, and the return value of, the 'signal' function, and whose values compare unequal to the address of any declarable function; and the following, which expand to positive integer constant expressions with type 'int' and distinct values that are the signal numbers, each corresponding to the specified condition:

SIGABRT -> abnormal termination, such as is initiated by the abort function
SIGFPE -> an erroneous arithmetic operation, such as zero divide or an operation resulting in overflow
SIGILL -> detection of an invalid function image, such as an invalid instruction
SIGINT -> Receipt of an interactive attention signal
SIGSEGV -> an invalid access to storage
SIGTERM -> a termination request sent to the program

Here, there are three important statements regarding macros defined in signal.h:

  1. "expand to constant expressions with distinct values that have type compatible with the second argument to, and the return value of, the 'signal' function".

    My understanding: These macros are replaced by a value which has the type void (*)(int), i.e., an address to a function: which takes an int as argument and has return type similar to the return type of signal function, i.e., void.

  2. "whose values compare unequal to the address of any declarable function".

    My understanding: The address to a function returned by these Macros is not equal to any declarable function. But I'm not sure what exactly is a Declarable function.

  3. "the following, which expand to positive integer constant expressions with type 'int' and distinct values that are the signal numbers".

    My understanding: I don't understand this.

Cinverse
  • 106
  • 7

1 Answers1

4

Part 1

  1. "expand to constant expressions with distinct values that have type compatible with the second argument to, and the return value of, the 'signal' function".

    My understanding: These macros are replaced by a value which has the type void (*)(int), i.e., an address to a function: which takes an int as argument and has return type similar to the return type of the signal function, i.e., void.

Your understanding has a mixture of correct and incorrect understanding. You could take a look at Understanding typedefs for function pointers in C for some more information.

The official declaration of §7.14.1.1 The signal function is:

void (*signal(int sig, void (*func)(int)))(int);

However, it would be easier to understand if there was a typedef such as:

typedef void (*SignalHandler)(int signum);

so that the function could be declared as:

SignalHandler signal(int signum, SignalHandler handler);

Now, in your understanding, the SIG_DFL, SIG_ERR, SIG_IGN are indeed values of type void (*)(int) — which is the same type as SignalHandler. But the return type of the function pointers is void, but the return type of signal() is SignalHandler or void (*)(int) — not void as you state.

Part 2

  1. "whose values compare unequal to the address of any declarable function".

    My understanding: The address to a function returned by these Macros is not equal to any declarable function. But I'm not sure what exactly is a declarable function.

It means that no matter how you write a function declaration:

extern void handler(int signum);
void handler(int);
…

you cannot write a function declaration where the address of the function would equal any of the constants SIG_DFL, SIG_ERR, or SIG_IGN. This is normally achieved by using values such as 0, -1, 1 as the addresses. (These are the values used on macOS Big Sur 11.7.1; I believe they are widely used values.)

Part 3

  1. "the following, which expand to positive integer constant expressions with type 'int' and distinct values that are the signal numbers".

An 'integer constant expression' is important in C. Not all expressions that involve only constant integers are integer constant expressions — beware! You can use integer constant expressions in the dimension of arrays defined at file scope, for example, or in case labels, and various other places where you're not allowed to use other integer expressions, even if they're integer expressions involving only constant integer values.

The definition means:

  1. They are macros, so you can test them with #if defined(SIGINT).
  2. The numbers corresponding to SIGINT etc are positive int values.
  3. They are distinct from each other, so SIGINT != SIGSEGV and so on for any pair of signal names listed in the standard.
  4. The values can be passed to signal() (so you can specify how the signal is to be handled) and to raise() in Standard C and to kill() in POSIX (so that the signal is sent, which will have effects that are implementation-defined.

The names and descriptions indicate the intended use of each signal.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • what is 'constant integer expression'? – Cinverse Nov 20 '22 at 07:32
  • `const int xyz = 13;` is a constant integer expression but is not an integer constant expression. – Jonathan Leffler Nov 20 '22 at 07:47
  • 1
    @JonathanLeffler: `const int xyz = 13;` is not an expression, so it is not a constant integer expression. I do not know what you are trying to say here. There is no definition of “constant integer expression” in the C standard. Objects can be `const`-qualified or not. An expression can use the value of a `const`-qualified object, but that does not make the expression constant or not. Maybe you are trying to describe an expression that always has the same value in some sense? But it is not clear. – Eric Postpischil Nov 20 '22 at 10:55
  • 2
    I misspoke in haste in the comment. Given a declaration (definition) `const int xyz = 13;`, you cannot write `xyz` where an 'integer constant expression' is required — such as in the definition of an array at file scope or in a case label in a `switch` statement. —— Separately, as noted, the standard doesn't mention 'constant integer expression', and saying that it does is a mistake in my answer. Nevertheless, not all expressions involving only constant integers are 'integer constant expressions' — an expression involving `xyz` defined as shown would not be an integer constant expression. – Jonathan Leffler Nov 20 '22 at 15:47