-1

I have a problem with the following code:

#include <stdlib.h>
#include <stdio.h>
void red(int *);
int main()
{
    int *wsk,i;
    wsk = (int*)malloc(10*sizeof(int));
    for(i=0;i<10;i++)
    {
        wsk[i]=i+100;
        printf("value: %d num pointer:%p \n",wsk[i],wsk+i);
    }

    printf("\n\n");
    red(wsk);
    printf("\n\n");
    for(i=0;i<11;i++)
    {
        printf("value: %d num pointer:%p \n",wsk[i],wsk+i);
    }
    free(wsk);
    return 0;
}
void red(int* wsk)
{
    int i;
    wsk = realloc(wsk,11*sizeof(int));
        for(i=0;i<11;i++)
    {
        printf("value: %d num pointer:%p \n",wsk[i],wsk+i);
    }
}

On the school computer this code works and the wsk pointer in the function red is the same as in main. When I run the same code on a different computer I get different results

Results from my computer:

in my computer

Results from the other computer:

other computer

Increasingly Idiotic
  • 5,700
  • 5
  • 35
  • 73
  • 2
    "Works there, not here" is usually the same as "has undefined behaviour". – Yunnosch May 15 '18 at 19:59
  • 1
    `wsk` in the function is a **copy** of the `wsk` in `main`. It's reallocated value does not find its way back to `main`. – Weather Vane May 15 '18 at 20:02
  • 1
    You're calling `realloc` within `red()`, but that pointer is not passed outside that function. You're likely invalidating `wsk` in the main function. – Fred Larson May 15 '18 at 20:02
  • 1
    side note, [you should not cast the result of malloc](https://stackoverflow.com/q/605845/9614249) – Increasingly Idiotic May 15 '18 at 20:03
  • C is pass-by-value. Print out the value of the pointer `wsk` in `main()` before and after your call to `red(wsk);`. You'll note that it doesn't change, even if the value *inside* your `red()` function does change. – Andrew Henle May 15 '18 at 20:03
  • @IncreasinglyIdiotic it was important more than 19 years ago before the C99 standard. Now unless you use the prehistoric C standard, functions with no prototypes are not allowed. – 0___________ May 15 '18 at 20:07
  • @PeterJ_01 brain fart? This question is not about function prototypes, or was a comment deleted? – Weather Vane May 15 '18 at 20:15
  • casting malloc was dangerous if you had forgotten to include stdlib.h with the malloc prototype. Nowadays it does not matter as the "new" (almost 20 years old) C standard does not allow implicit function declarations. – 0___________ May 15 '18 at 20:20
  • @PeterJ_01, it is useless, nevertheless. Casts are bad, if you don't understand your witchcraft. And, BTW, many compilers still use the implicit `int` rule. – Jens Gustedt May 15 '18 at 20:51
  • @JensGustedt - no programmers use old standards. In c99+ casts are even safer for the humans if you cast to the type which is sizeofed (compilers are ignoring them). Example: `double *f = (int *)malloc(n * sizeof(int))`. - you will get the warning. Without the cast - no warning. – 0___________ May 15 '18 at 21:18
  • @PeterJ_01, and how do you guarantee that you always use the same type in the cast as in the `sizeof`? I probably also would get a warning for `double *f = (long*)malloc(n * sizeof(int))`. The recommended practice for such cases is to use `double *f = malloc(n * sizeof *f)` because it just never can go wrong. – Jens Gustedt May 16 '18 at 07:51

2 Answers2

4

The realloced address is only kept in the red function scope. Then you dereference the old pointer.

void red(int** wsk)
{
    int i;
    *wsk = realloc(*wsk,11*sizeof(int));
    ...
}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 2
    There's no need for an `int **`. Just *return* the new value. – Andrew Henle May 15 '18 at 20:05
  • 3
    I do not change the initial OP idea. And it shows the scope of the variables – 0___________ May 15 '18 at 20:05
  • 1
    True, but I'd say the initial OP idea was fundamentally broken. Adding pointer indirection might be a bit much for someone not familiar enough with C to know it's a pass-by-value language. – Andrew Henle May 15 '18 at 20:09
  • I did so, but my teacher said that the pointer to the pointer is not necessary because the tables are passed through the references – aerodynamic96 May 15 '18 at 20:11
  • 2
    The teacher should learn something about the scopes of the variables. – 0___________ May 15 '18 at 20:12
  • ok, just how I did in school void red (int *wsk) and i changed the size of memory it worked well in main() – aerodynamic96 May 15 '18 at 20:44
  • It is undefined behavior. Depending how the realloc works - it may keep the same start address or not. In this particular case in your school the realloced chunk of memory has the same start address. It is just incidental. – 0___________ May 15 '18 at 21:21
2

Your function void red(int* wsk) passes the wsk by value meaning a local version of wsk is copied to the function and changes made within red will not be reflected in main.

One approach to solve this is to return the new value of wsk to main:

int* red(int* wsk) // Return type changed
{
    int i;
    wsk = realloc(wsk,11*sizeof(int));
    for(i=0;i<11;i++)
    {
        printf("value: %d num pointer:%p \n",wsk[i],wsk+i);
    }

    return wsk; // Return new wsk
}

And then change the call in main to

wsk = red(wsk);

So that the wsk in main is updated to the wsk returned by red.


Also note that you never initialized wsk[10] after calling realloc() and accessing it will result in more undefined behavior.

Increasingly Idiotic
  • 5,700
  • 5
  • 35
  • 73