Using void pointer to an array
Solution 1
You need to cast arr
before adding j
. Here is a minimal fix:
x = *(((int *)arr)+j);
but I think it's clearer to write:
x = ((int *)arr)[j];
Solution 2
You are doing pointer arithmetic on void *
which is not valid in C.
In GNU C (C with gcc extensions), it is actually permitted and the sizeof (void)
is considered to be 1.
http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
"addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1."
Solution 3
The C standard does not define behaviour for arithmetic of void *
, so you need to cast your void *
to another pointer type first before doing arithmetic with it.
Some compilers [as an extension] treat pointer arithmetic of void *
the same as char *
, so each ‘+1’ will only increase the address by 1, rather than by the size of the pointed-to object. This is not standardised though so you can't rely on this behaviour.
Solution 4
you should not add numbers to void pointers. cast it before. (x = *((int *)arr+j);
)
When you add number to a pointer, the compiler multiply this number with the size of the type that is pointed, so if you add number to a pointer to wrong type, you will get wrong result.
if I remember correct, add to void* is illegal, but some compilers adds the exact number in bytes (like it is char*). `
Anusha Pachunuri
Updated on January 11, 2020Comments
-
Anusha Pachunuri over 4 years
I was just trying to use a void pointer to an integer array ,I tried to see if i can print the array back by casting it back into int. But it is giving me some random value. Can you tell me where i am going wrong?
#include<stdio.h> #include<stdlib.h> int main(){ int a[5]; int x; int j; a[0]=1; a[1]=2; a[2]=3; a[3]=4; void *arr=a; for(j=0;j<4;j++){ x = *(int *)(arr+j); printf("%d",x); } return 0; }
Output is this:
133554432131072512
Why is it not pinting elements of array a[] i.e 1,2,3,4 ?
-
Anusha Pachunuri over 12 yearsWorked like a charm. Thanks a ton.
-
Anusha Pachunuri over 12 yearsI was wondering why *(int *)(arr+j) is wrong? Can you please explain me?
-
TOMKA over 12 years@AnushaPachunuri: Please see my answer, but to sum up, it's wrong because you can't add numbers to
void *
, you need to convert thevoid *
first and then add numbers to it. -
Anusha Pachunuri over 12 yearsoh so u mean pointer arithmetic is not applicable for void * pointers. Well i see the point. Thanks for a great explanation.
-
Jonathan Leffler over 12 years+1: for pointing out that arithmetic on
void *
is a GCC extension. -
Jonathan Leffler over 12 yearsISO/IEC 9899:1999. §6.2.5 ¶19 The void type comprises an empty set of values; it is an incomplete type that cannot be completed. and then in ¶20 it adds A pointer type may be derived from a function type, an object type, or an incomplete type ... where an incomplete type is clearly not an object type, so you cannot treat
void *
as a pointer to an object type. §6.5.2 The additive operators says For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. So you cannot do arithmetic onvoid *
. -
TOMKA over 12 years@JonathanLeffler: The behaviour is not defined by the C standard, but it is not explicitly undefined either, and it's usually these areas where C implementations put in such behaviour and call it an extension.
-
ouah over 12 years@dreamlax as mentioned by @JonathanLeffler addition of an integer and an operand of
void *
type is a clear violation of the constraints of the additive operator (6.5.6p3). So it requires a diagnostic and the implementation is free to not translate the program. -
TOMKA over 12 years@ouah: I'm not arguing anything here, if anything I'm agreeing with you; I said that some compilers treat it as an extension. What I'm saying is that it is not undefined behaviour to use
void *
in arithmetic, I'm saying it is simply not defined at all (i.e. the standard does not define any behaviour for arithmetic involvingvoid *
). There is a massive difference between undefined behaviour and something that is not defined by the C standard.