INF: The Proper Type for Pointer to jmp_buf Is void *

ID Number: Q34921

5.00 5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a

MS-DOS | OS/2

Summary:

The setjmp() and longjmp() functions use a parameter of type jmp_buf.

(The type jmp_buf is declared in SETJMP.H.) Using the & operator

("address of") on a variable of type jmp_buf and assigning it to a

pointer of type jmp_buf generates the following warnings in C 5.1:

warning C4046: '&' on function/array, ignored

warning C4047: '=' : different levels of indirection

Leaving the ampersand (&) off and assigning the value to a pointer

of type jmp_buf generates the following warning in C 5.1, 6.0, 6.0a,

6.0ax, and C/C++ version 7.0:

warning C4047: '=' : different levels of indirection

To solve the problem, declare the pointer to be of type void *. Then,

assign it without using the ampersand (see the sample code below).

More Information:

Because the header file SETJMP.H defines a jmp_buf as an array of

integers, using the ampersand operator generates the warning described

above. The reason for choosing an array type rather than a structure

has to do with common C coding practices and is described in section

4.6 of the Rationale for the ANSI C Standard.

Basically, the setjmp() function must change the jmp_buf parameter in

order to record where to come back to when longjmp() is executed.

Elsewhere, the standard defines setjmp() as taking a single parameter

of type jmp_buf, NOT of type "pointer to jmp_buf." The jmp_buf cannot

be a structure, because structures are passed by value and therefore

could not receive changes made by setjmp(). Because arrays are passed

by reference (that is, by their address), setjmp() can change a

parameter that is passed as an array.

The declaration for badptr (below) declares it to be of type "pointer

to array of integer," not "pointer to integer." Doing an assignment

with different pointer types gives the C4047 warning error. (In order

to do the assignment without a warning, badptr would have to be

"pointer to integer," because that's the compatible pointer type for

"array of integer.")

Instead, using goodptr, declared "pointer to void," allows the

assignment to be made without generating a warning. This is also

portable code. Note that you cannot use indirection (or subscripting,

which is a form of indirection) on void pointers.

However, because you don't know what's in the jump buffer anyway, this

should be no problem. (The contents of the jump buffer are

implementation-dependent and could even differ from version to version

of the same compiler. Any code that directly manipulates jump buffers

is also implementation-dependent and non-portable.)

Sample Code

-----------

/* Compiler options needed: none

*/

#include <setjmp.h>

jmp_buf buf;

jmp_buf *badptr;

void *goodptr;

void main()

{

badptr = &buf;

/* C 5.1 warning C4046: '&' on function/array, ignored */

/* C 5.1 warning C4047: '=' different levels of indirection */

badptr = buf;

/* warning C4047: '=' : different levels of indirection */

goodptr = buf;

}

Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax 7.00