0

like this:

void** a = calloc(4,4);
printf("%x,%x",a,a+1));

the result is 1516c0,1516c8

why the step is 8? I don't want use (char*) to convert the type,what should I do?

Gerhardh
  • 11,688
  • 4
  • 17
  • 39
  • 7
    Pointer arithmetic. `sizeof (void *)` is 8 on your system, so `a + 1` goes 8 bytes forward to go to the next `void *`. Also the correct format specifier for pointers is `%p`. – mediocrevegetable1 Aug 09 '21 at 07:20
  • 1
    Welcome to SO. You forgot important details. What step did you expect? 4? 1? Why? "what should I do?" What do you want to achieve? – Gerhardh Aug 09 '21 at 07:25
  • 1
    As mediocrevegetable1 mentioned, pointers need format specifier `%p`. And to be precise you must provide `void*` which means you need to cast your `void**` to `void*` for printing it. – Gerhardh Aug 09 '21 at 07:26
  • As with array indexing, adding 1 moves to the next *element* not the next *byte*. `a + 1` is the same as `&a[1]`. – Weather Vane Aug 09 '21 at 07:30
  • I want to make the step become 1 – GuoHaodong Aug 09 '21 at 07:35
  • 2
    Step by 1 *what*? For what purpose? Adding `1` does make it step by 1. Why do you `calloc(4,4)` when the pointer size on your system is clearly `8`? – Weather Vane Aug 09 '21 at 07:37
  • 1
    Use `%p` to print pointer values, not `%x`. On a typical 64-bit system, pointers are 8 bytes and integers are 4 bytes, so at best you'd only be printing half of the pointers, and you may not be printing any of the second pointer at all. – Tom Karzes Aug 09 '21 at 07:48
  • "I want to make the step become 1" The less horrible solutions for that involve "use (char*) to convert the type", which you do NOT want. Please decide what is the more important of those two requirements. You might also want to take one logical step back and describe what you really want to achieve, i.e. please consider whether we are looking at a https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Yunnosch Aug 09 '21 at 07:57
  • `a+1` depends on the type of `a`, not on the address of `a` (nor the number of bytes reserved at that address). – U. Windl Aug 09 '21 at 08:27
  • pointer arithmetic on `void*` is illegal. Duplicate: [Pointer arithmetic for void pointer in C](https://stackoverflow.com/q/3523145/995714), [Should the compiler warn on pointer arithmetic with a void pointer?](https://stackoverflow.com/q/20967868/995714), [Why does incrementing a void pointer by 1 moves one byte ahead but it's 4 bytes for an integer pointer,8 for double?](https://stackoverflow.com/q/16336757/995714) – phuclv Aug 09 '21 at 08:39
  • 1
    @phuclv Pointer arithmetic on `void**` isn't, however. – Lundin Aug 09 '21 at 08:39

3 Answers3

2

Printing pointers with %x isn't well-defined, you should use %p instead.

a+1 performs pointer arithmetic on type void**, meaning you get the byte size of the pointed-at item, a void*. So depending on how large such a pointer is on your system, you'll get an address change accordingly. Apparently your system has 64 bit pointers (likely 64 bit address bus) hence 8 bytes.

Using absolute values to calloc is fishy code overall. Not sure what you are trying to achieve with that.

If you want a type-generic pointer that can iterate through generic chunks of data byte by byte, the correct type to use is unsigned char*. If you don't want to use that for some artificial reason, then tough luck - no can do.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • since when is arithmetic on void* defined? – Raildex Aug 09 '21 at 08:31
  • 1
    @Raildex Since the first C standard? It's arithmetic leading to pointed-at `void` which isn't defined. So if it had been `void* a`, the code wouldn't compile. `void**` is however just an ordinary pointer type without special rules. – Lundin Aug 09 '21 at 08:33
  • yes, I would like use "generic-type" in c, because some type size is less than 8B eg: int is 4B, I want to move the pointer byte by byte. I use the (char*) , it work pretty.Is necessary change it? – GuoHaodong Aug 09 '21 at 08:34
  • @GuoHaodong That's what I wrote in the answer, yes? Except it should be `unsigned char*` if you mean to access the data through that pointer. `char*` has implementation-defined signedness and therefore shouldn't be used when dealing with raw binary data. – Lundin Aug 09 '21 at 08:39
0

As mentiond the size of void * is 8 on your system so it goes 8 bytes forward. Any way, you just need to change some thing and you don't need to use char * for this case. In addition, using %p to print pointers is a better choice:

void** a = calloc(4, sizeof(void *));
printf("%p,%p",a,a+1));
G. Emadi
  • 230
  • 1
  • 8
0

I believe that you have a problem with understanding the difference between the physical addresses and the references. Pointer arithmetic in C is done using the objects referenced by the pointers. When you print the pointer using "%p" or "%x" (not good as it is wrong format) you get the physical (byte) address.

  1. You probably use void ** because pointer arithmetics on void * does not work on most compilers that do not have special extensions as gcc.

  2. If you want the address to be increased by one simply use char * pointer instead of void *

  3. If you want to print the difference in pointer arithmetics (not physical bytes):

int main(void)
{
    void **a;
    printf("%" PRIiPTR "\n", a - (a+1));
}
0___________
  • 60,014
  • 4
  • 34
  • 74