1

Below is the program:

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

int *glob_var;
int* copy(void *a,int size)
{
    int *t=(int *)calloc(1,sizeof(int));
    int i;
    int *glob_var=(int *)calloc(size,sizeof(int));
    printf("glob_var=%p\n",glob_var);
    printf("a=%p\n",a);
    t=glob_var;
    for(i=0;i<size;i++)
    {
        *glob_var=*(int *)a;
         glob_var++;

         (int *)a++;
        // printf("a=%p\n",a);

    }
    glob_var=t;
     for(i=0;i<10;i++)
    {
       printf("%d\t",*glob_var);
       glob_var++;

    }
glob_var=t;
printf("\n%p\n",glob_var);
return t;
}
int main() {
    // Write C code here
    int a=0x123456,i;
    int *var=(int *)calloc(10,sizeof(int));
    int *temp;
    temp=var;
    for(i=0;i<10;i++)
    {
        *var=i;
        var++;

    }
    var=temp;
    for(i=0;i<10;i++)
    {
       printf("%d\n",*var);
        var++;


    }
    var=temp;
    printf("var=%p\n",var);

    glob_var=copy(var,10);
    printf("%p\n",glob_var);

    for(i=0;i<10;i++)
    {
       printf("%d\t",*glob_var);
       glob_var++;

    }
    return 0;
}

However, the output I got is :

0       16777216        65536   256     1       33554432        131072  512     2       50331648

I was expecting: 0 1 2 3 4 5 6 7 8 9.

But, in the copy() function, if I replace (int *)a++; with a=(int *)a+1; it is working.

My question is: What is wrong with the current program?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Karna Rai
  • 19
  • 4

1 Answers1

1

Arithmetic on a pointer-to-void (void*) is not allowed in C1 and your compiler should warn you about that (at the very least) in the following line:

(int *)a++;

When I compile your code (using the clang-cl compiler in Visual Studio), I do, indeed, get two warnings for that line:

warning : arithmetic on a pointer to void is a GNU extension [-Wpointer-arith]
warning : expression result unused [-Wunused-value]

The first of these addresses the issue mentioned in my opening line (and discussed in the footnote) but it is the second that should be ringing alarm bells. That shows that the cast isn't working as intended – it is actually applied to the result of the a++ operation, because the cast has lower precedence than the post-increment.

However, when you use a = (int *)a + 1;, then all is working as intended, because the a pointer is cast to an int* before the arithmetic is performed (and then implicitly cast back to a void* for the assignment).

(There are other issues in your code, like the re-declaration of glob_var in your function, and the use of non-void pointers as arguments for the %p format specifier in several printf calls – but these are not really related to your reported problem. Also, this is worth a read: Do I cast the result of malloc?)


1 Some C compilers, such as GCC, do allow arithmetic on void* pointers, but I do not know what the 'base unit size' is for such operations. One would have to read the GCC manual to determine that, but it may very well by just 1, rather than the sizeof(int) required for your program, as presented, to work. Indeed, if that assumption is correct, and sizeof(int) is 4 on your platform, it would explain the three "garbage values" between successive 'real' data in your output.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83