Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a reason to use C language pointers like this &(*foo)?

Tags:

c

pointers

I use to code pointers like this when I need to change the original memory address of a pointer.

Example:

static void get_line_func(struct data_s *data,
                                char **begin)
{
    data->slot_number = strsep(&(*(begin)), "/");
    data->protocol = *begin;
    strsep(&(*begin), ">");
    data->service_name = strsep(&(*begin), "\n");
}

I mean, isn't &(*foo) == foo?

like image 558
Henrique Gouveia Avatar asked Dec 08 '25 18:12

Henrique Gouveia


1 Answers

There is no reason to do that directly. However, the combination can arise in machine-generated code (such as the expansion of a preprocessor macro).

For instance, suppose we have a macro do_something_to(obj) which expects the argument expression obj to designate an object. Suppose somewhere in its expansion, this macro takes the address of the object using &(obj). Now suppose we would like to apply the macro to an object which we only hold via a pointer ptr. To designate the object, we must use the expression *ptr so that we use the macro as do_something_to(*ptr). That of course means that&(*ptr) now occurs in the program.

The status of the expression &*ptr has changed over the years. I seem to remember that in the ANSI C 89 / ISO C90 dialect, the expression produced undefined behavior if ptr was an invalid pointer.

In ISO C11 the following is spelled out (and I believe nearly the same text is in C99), requiring &* not to dereference the pointer: "if the operand [of the address-of unary & operator] is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue". Thus in the modern C dialect, the expression &*ptr doesn't dereference ptr, hence has defined behavior even if that value is null.

What does that mean? "constraints still apply" basically means that it still has to type check. Just because &*P doesn't dereference P doesn't mean that P can be a double or a struct; it has to be a pointer.

The "result is not an lvalue" part is potentially useful. If we have a pointer P which is an value, if we wrap it in the expression &*P, we obtain the same pointer value as a non-lvalue. There are other ways to obtain the value of P as a non-lvalue, but &*P is a "code golfed" solution to the problem requiring only two characters, and having the property that it will remain correct even if P changes from one pointer type to another.

like image 144
Kaz Avatar answered Dec 10 '25 11:12

Kaz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!