1

I just fail to understand the error in the following program.What I have done is I've assigned the address of an array of size 5 to a pointer ptr of type (*)[].There is no type mismatch and it's ok as far as that goes.But then I want to print the value ptr+1.As I expected, it shows an error about unspecified bounds.But it just misses me how the same ptr+1 works fine when I cast it to type void*.

Casting is fine, but before it comes to that,how can the program calculate ptr+1 as it simply doesn't know the bounds? How would it know whether to move 5 elements ahead, or 8 elements ahead or any elements ahead?Why doesn't (void*)ptr+1 show the same error as ptr+1?

To better highlight the whole thing, I have also used a pointer ctr which is explicitly declared to be of type (*)[5] instead of (*)[]. Please give me the technical reasons behind this.Thank you.

#include<stdio.h>

int main(void)
{
 int ar1[5]={1,5,3,8,9};
    int (*ptr)[]=&ar1,(*ctr)[5]=&ar1;
    printf("%p\n",ptr+1);      //ERROR about unspecified bounds
    printf("%p\n",(void*)ptr+1);    //It's ok
    printf("%p\n",ctr+1);       //It's ok
}

PSST!! The last two correct printf()s don't produce the same value.If I comment out the incorrect printf("%p\n",ptr+1); line, this is the output.

0023FF25

0023FF38

PSST!! I checked it again, int the ptr+1 part of (void*)ptr+1 , a 1 is simply being added to the numeric value of ptr.What's going on?

Thokchom
  • 1,602
  • 3
  • 17
  • 32

2 Answers2

1

as per your code

int (*ptr)[]

ptr is a pointer to an array of UNKNOWN size.So till now compiler have no idea about the size where ptr is pointing.When you are trying to make an increament, compiler still don't have any idea how much to increment. A pointer increament will be a addition of the sizeof(pointed element).So you are getting error "unspecified bound".

Now for your remaining two questions, For better understanding allow me to rephrase your both questions in one- "WHY (VOID*) IS BEHAVING LIKE (CHAR*)"??(hw was that :)?) your answer is

In the C standard (N1256 draft):6.2.5-27:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.

Dayal rai
  • 6,548
  • 22
  • 29
  • That's not why the compiler treats pointer *arithmetic* on `void*` the same way as `char*`. On most systems, `int*` and `char* have the same representation and alignment requirements, but arithmetic on them behaves differently. Arithmetic on `void*` is a gcc-specific extension; in standard C, it's a constraint violation. – Keith Thompson Aug 06 '13 at 06:32
0

Please give me the technical reasons behind this.

The technical reason is that when adding one, your compiler tries to jump to the next instance of that type.

Example: adding one to an int pointer will increment it by four because an int is 4 bytes long and it will then point to the next int.

In your example, with ptr you never specified the size. It's impossible to jump to the next element because the size of this element is not known. Once you specified the size by making it point to an array of exactly 5 elements, it worked again.

When casting ptr to void, it became easy again to go to the next element. The compiler just added one byte.

In your run:

ptr is 0023FF24

((void*)ptr) + 1 is 0023FF25 (the base address plus 1 byte for one element of "void")

ctr is 0023FF24 (same as ptr)

ctr + 1 is 0023FF38 (the base address, plus 20 (5*sizeof(int)) bytes for one element of int (*)[5])

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • So in a 32 bit system, if we add 1 to an integer pointer it jumps 4 places, but a void pointer jumps by 1 place/bye when incremented? – Thokchom May 02 '13 at 10:59
  • Correct. Any pointer arithmetic is multiplied by `sizeof(type pointed to)` with `void` being special as it has no size but is treated as size 1. So `int* x; x += 2;` will advance the value of x by 8 (two times the size of int). `void* x; x += 2;` will advance the value of x by 2 (two times 1). – nvoigt May 02 '13 at 11:03
  • 2
    @Thokchom Pointer arithmetic on `void*`s is not allowed by the standard. Some compilers, like gcc, allow it as an extension. I'm not aware of a compiler that treats a `void*` different from a `char*` in pointer arithmetic if it allows arithmetic on `void*`s at all, but you shouldn't rely on it. – Daniel Fischer May 02 '13 at 11:35