-1

My program has 3 int arrays (pointers) declared in the main function. The user enters the length of array A, which is then filled with random numbers.

Then, a function is called which takes all 3 arrays as its arguments. It takes all the even numbers from array A and puts them into array B, and all the odd numbers into C. The sizes of B and C need to be the same as the number of their elements. The elements of B are then printed.

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

int velA, velB, velC; //the sizes of all the arrays

void napravi(int a[], int *b, int *c);

void main() {
    int *a, *b, *c;
    int i;
    srand(time(NULL));

    printf("Enter array lenght:"); 
    scanf("%d", &velA);
    getchar();

    a = (int*)calloc(velA, sizeof(int));
    b = (int*)malloc(4); //I have to initialize the variable in order to pass it as an argument ?
    c = (int*)malloc(4);

    for(i = 0; i < velA; i++) {
        a[i] = rand() %101;
    }

    napravi(a, b, c);

    for(i = 0; i < velB; i++) {
        printf("%d  ", b[i]);
    }

    free(a);
//  free(b); //Windows has triggered a breakpoint in .exe
//  free(c);
    getchar();
}

void napravi(int a[], int *b, int *c) {
    int i;
    int j = 0, k = 0;

    for(i = 0; i < velA; i++) {
        if(a[i] % 2 == 0) {
            j++;
        }
        else {
            k++;
        }
    }
    free(b);
    free(c);
    b = (int*)calloc(j, sizeof(int));
    c = (int*)calloc(k, sizeof(int));


    j = 0; k = 0;

    for(i = 0; i < velA; i++) {
        if(a[i] % 2 == 0) {
            b[j] = a[i];
//          printf("\n%d | %d", a[i], b[j]);
            j++;
        }
        else {
            c[k] = a[i];
            k++;
        }
    }
    velB = j;
    velC = k;
}

There are 2 problems with this code.

  • First, if the user enters a value that is bigger than something around ~420, it starts to print junk values like -17987777...
  • Second, when I attempt to free(b) and free(c) at the end, the program crashes with an error "Windows has triggered a breakpoint in my.exe".
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Kidades
  • 600
  • 2
  • 9
  • 26

2 Answers2

5

in C, function parameters are passed by value. So, from napravi() function, you cannot change b itself. However, you can certainly change the value at adrress pointed by b, i.e., *b.

If you need to change b from napravi() you need to pass a pointer to b from main().

if the user enters a value that is bigger than something around ~420, it starts to print junk values like -17987777...

You're facing undefined behaviour in your code.

for(i = 0; i < velB; i++) {
        printf("%d  ", b[i]);
    }

in above code, velB value is updated properly (as expected from the code), but b is not (as expected from the napravi()function). So, you're overruning the allocated memory area, creating UB.

when I attempt to free(b) and free(c) at the end, the program crashes with an error "Windows has triggered a breakpoint in my.exe".

Result of UB.


Note: Please do not cast the return value of malloc() and family in C.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • I did pass a pointer. b is a pointer. When I don't cast the return value of malloc(), the compiler gives a warning. – Kidades May 12 '15 at 10:36
  • 1
    @Kidades no, you need a pointer to a pointer, if you want to change the pointer itself. Got it? – Sourav Ghosh May 12 '15 at 10:37
  • 1
    @Kidades As per `C` standard, `void *` will be converted to any other data pointer safely. You don't need the casting. Are you sure you're using a `C` compiler? – Sourav Ghosh May 12 '15 at 10:42
  • I'm using VS2010 and it says: IntelliSense: a value of type "void *" cannot be assigned to an entity of type "int *" – Kidades May 12 '15 at 10:44
  • 1
    @Kidades no comments about `VS2010`. _Word of Caution: when it comes to standard compilance, never trust MS._ – Sourav Ghosh May 12 '15 at 10:46
  • @Kidades _cannot be assigned to_ You are using a C++ compiler as a C compiler. You need to change the option(/TP --> /TC) or change the file extension(.cpp --> .c). – BLUEPIXY May 12 '15 at 10:53
  • @SouravGhosh What do you mean with b is not updated properly? – Kidades May 12 '15 at 10:56
2

try this

int main(void) {
    int *a, *b, *c;
    int i;
    srand(time(NULL));

    printf("Enter array lenght:"); 
    scanf("%d", &velA);
    getchar();

    a = (int*)calloc(velA, sizeof(int));
    //b = NULL;//There is no need to set the value
    //c = NULL;//NULL is better than malloc(4)

    for(i = 0; i < velA; i++) {
        a[i] = rand() %101;
    }

    napravi(a, &b, &c);

    for(i = 0; i < velB; i++) {
        printf("%d  ", b[i]);
    }

    free(a);
    free(b);
    free(c);
    getchar();
    return 0;
}

void napravi(int a[], int **b, int **c) {
    int i;
    int j = 0, k = 0;

    *b = *c = NULL;
    velB = velC = 0;
    if(a == NULL || velA == 0)
        return;

    for(i = 0; i < velA; i++) {
        if(a[i] % 2 == 0) {
            j++;
        }
    }

    if(velB = j)
        *b = (int*)malloc(velB * sizeof(int));
    if(velC = velA - velB)
        *c = (int*)malloc(velC * sizeof(int));


    j = 0; k = 0;

    for(i = 0; i < velA; i++) {
        if(a[i] % 2 == 0)
            (*b)[j++] = a[i];
        else
            (*c)[k++] = a[i];
    }
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70