-2

I wanted to allocate memory and scanf array in one function, but it gives segmentation fault (core dumped) error. Thank you for help.

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

void scanf_array (int **array_pp, int size);

int main ()
{
  int *array_p, size;
  scanf ("%d", &size);
  scanf_array (&array_p, size);
  for (int i = 0; i < size; i++)
  {
    printf ("%d", array_p[i]);
  }
  return 0;
}

void scanf_array (int **array_pp, int size)
{
  *array_pp = (int *)malloc (size * sizeof (int));
  for (int i = 0; i < size; i++)
  {
  scanf ("%d", array_pp[i]);
  }
}
Franta_B
  • 55
  • 3
  • `array_pp[i]` is not even in array you've allocated. Also you need to provide `scanf` with address of the element, not its value. Should be something like `&(*array_pp)[i]`. – Alex Skalozub Feb 18 '20 at 19:29
  • read this: https://stackoverflow.com/questions/2565039/how-are-multi-dimensional-arrays-formatted-in-memory/59691323#59691323 – sqr163 Feb 18 '20 at 20:08

3 Answers3

2
scanf ("%d", array_pp[i]);

is wrong. int **array_pp is meant to be pointer to an array of ints. So you want to dereference the pointer, then pass the address of ith element to scanf:

scanf ("%d", &(*array_pp)[i]);
scanf ("%d", (*array_pp) + i);  // means the same

Remember to free(array_p).

Because sometimes using pointer to pointer sematics is hard, it's sometimes clearer to use a temp pointer for me:

void scanf_array (int **array_pp, int size)
{
  int *array_p = malloc(size * sizeof (*array_p));
  for (int i = 0; i < size; i++) {
     scanf ("%d", &array_p[i]);
  }
  *array_pp = array_p;
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    A short discussion on why the `(..)` are needed and a link to [operator precedence](https://en.cppreference.com/w/c/language/operator_precedence) may help further. – David C. Rankin Feb 18 '20 at 20:03
1

Is scanf ("%d", &(*array_pp)[i]); you're looking for?

Eric
  • 1,685
  • 1
  • 17
  • 32
  • It's more than 10 years since I've worked with C++ so probably my memory is getting a bit rusty. My way of thinking was that [] operator is a simple memory address offset array[i] == array + i, but to think of it you're right, array[i] == *(array + i), sorry it's been a while – Eric Feb 18 '20 at 20:48
0

The problem is the following line:

scanf ("%d", array_pp[i]);

The expression array_pp[i] would be correct if array_pp was a pointer to the first element of an array. However, it is a pointer to a single variable of type int *. Since a single variable is equivalent to an array of size 1, the only permissible index that is not out of bounds would be array_pp[0]. However, for single variables, it is common to write *array_pp instead, even if it accomplishes exactly the same thing as array_pp[0]. This is because indexing is generally only used with "proper" arrays, i.e. arrays with at least 2 elements.

The expression *array_pp (or array_pp[0] if you prefer) gives you access to the variable

int *array_p

from the function main. Since that pointer now points to the first element of a dynamically allocated array of type int, you can use the indexes 0 to size on that pointer. So you could write either

(*array_pp)[i]

or

array_pp[0][i]

in your loop, where i is a value between 0 and size.

As stated before, even if both expressions accomplish exactly the same thing, it is better to write (*array_pp)[i] instead of array_pp[0][i].

However, the function scanf() requires the address of the array element to write to. So the line should be changed to the following:

scanf ("%d", &(*array_pp)[i]);

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39