0

This is the same concept as Pointer arithmetic for void pointer in C except my data type is a void** instead of a void*

#include <stdlib.h>
#include <stdio.h>

int main() {
    int foo [] = {1, 2};
    void* bar = &foo;
    void** baz = &bar;
    void** bazplusone = baz + 1;

    // cast to void* to make printf happy
    printf("foo points to %p\n", (void*)foo);
    printf("baz points to the address of bar and is %p\n", (void*)baz);
    printf("bazplusone is an increment of a void** and points to %p\n",(void*)bazplusone);
    return 0;
}

which results in the following output for my version of gcc:

foo points to 0x7ffeee54e770
bar is a void* cast of foo and points to 0x7ffeee54e770
baz points to the address of bar and is 0x7ffeee54e760
bazplusone is an increment of a void** and points to 0x7ffeee54e768

I have two questions:

  1. Is this legal according to the C standard?
  2. Assuming #1 is false, is there a way to generate a compiler error? Neither -pendandic-errors nor -Wpointer-arith complains about this small program
AnilRedshift
  • 7,937
  • 7
  • 35
  • 59
  • It is a GCC extension. I haven't tried it, but did you try `-std=c11 -pedantic` ? – Zan Lynx Jun 14 '20 at 01:27
  • `-std=c11 -pedantic` doesn't result in any errors – AnilRedshift Jun 14 '20 at 01:29
  • 1
    With the little test I just wrote I get a warning: `void-math.c:7:16: warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]` from GCC – Zan Lynx Jun 14 '20 at 01:31
  • 1
    Oh, by the way, math on a `void**` is completely legal. It increments the pointer to void* by the size of void*. – Zan Lynx Jun 14 '20 at 01:32
  • 1
    Like, you can't have an array of `void` but you can have an array of `void*`. – Zan Lynx Jun 14 '20 at 01:32
  • 2
    As long as `sizeof(t)` is defined for type `t`, then arithmetic on a `t *` is well-defined. In this case, `t` is `void *`. Since its size is defined, then arithmetic on a `void **` is also well-defined. – Tom Karzes Jun 14 '20 at 02:00

1 Answers1

2

I misunderstood what you were doing at first. I thought you were doing math on a void*. That is not allowed by the C Standard, but is allowed by a GCC (and clang) extension that treats it as math on a char*.

However, you are doing math on a void** which is perfectly OK. A void* is the size of a pointer and is not an undefined value. You can make arrays of void*s and you can do pointer math on a void** because it has a defined size.

So you will never get a warning for void** math because it is not a problem.

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • 1
    “Allowed” should be changed to “defined.” The C standard does not prohibit programmers or programs from doing things it does not define; they are generally allowed. And, if a C implementation that accepts strictly conforming programs accepts a program that does this (say because because it defines an extension), then the program is conforming as defined by the C standard. – Eric Postpischil Jun 14 '20 at 02:02
  • 1
    “A `void*` is the size of a pointer” should say “A `void *` has a known size.” “The size of a pointer” is not a fixed quantity; different types of pointers may have different sizes within a C implementation. – Eric Postpischil Jun 14 '20 at 02:05
  • @EricPostpischil Arithmetic on `void*` values is a constraint violation, not merely undefined behavior. A conforming implementation must diagnose it, and may either reject it or accept it. – Keith Thompson Jun 14 '20 at 03:24
  • @KeithThompson: Yes, it is a constraint violation. Nonetheless, the sentences I wrote above are true. – Eric Postpischil Jun 14 '20 at 09:55