Как обращаться к ячейкам динамического массива, переданного в функцию? - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Попытки присвоить значение или вывести на печать содержимое ячейки динамического массива заканчиваются Segmentation fault. Как правильно обращаться к ячейкам динамического массива в строках 22 и 25 внутри функции?
// example.c
#include <stddef.h>
#include <stdlib.h>
 
void external_function(float **, size_t *);
 
int main(void){
  float *dynamic_array;
  size_t size_of_dynamic_array=0;
 
  external_function(&dynamic_array,&size_of_dynamic_array);
 
  free(dynamic_array);
 
  return 0;
}
// external_function.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
void external_function(float **dynamic_array, size_t *size_of_dynamic_array){
 
   // Тут производятся некие вычисления, в результате которых можно узнать, какого
   // размера будет динамический массив. Допустим, результат равен десяти:
   *size_of_dynamic_array=10;
 
   // Выделение памяти
   *dynamic_array = (float*) malloc(*size_of_dynamic_array * sizeof(float));
 
   for(size_t m=0; m<*size_of_dynamic_array; ++m) {
 
      // Попытки присвоить значение или вывести на печать содержимое ячейки динамического
      // массива заканчиваются Segmentation fault
 
       // Например, попытка заполнить ячейку динамического массива через fscanf() заканчивается
       // Segmentation fault
       if(!fscanf(ptrfile, "%f",&dynamic_array[m])) { ... }
 
       // Или попытка вывести содержимое ячейки тоже заканчивается Segmentation fault
       printf("dynamic_array[%zu]=%.2f\n",m,dynamic_array[m]);
   }
 
}
gcc -pipe -g -O0 -Wall -Wextra -Wpedantic -Werror -Wshadow -std=c11 -c example.c
gcc -pipe -g -O0 -Wall -Wextra -Wpedantic -Werror -Wshadow -std=c11 -c external_function.c
gcc example.o external_function.o -o example

Решение задачи: «Как обращаться к ячейкам динамического массива, переданного в функцию?»

textual
Листинг программы
main() {
 int *a, size;
 
 f(&a, &size);
 ....
}
void f (int **pa, int *size)
{
   int *ax = *pa; // Начиная с этого места *a === *ax. Обе эти переменные (a и ax) - есть один 
    //четырехбайтовый  кусок  памяти. Все, что вы ни сделаете  с ax - вы делаете и с a
  ax = malloc... // a в main получит то же значение - указатель на выделенную память в куче
  ax = realloc(ax, newsize); // майновское a получило новое значение, указатель на новый кусок
  free(ax); // Кусок отдан на растерзание другим, но ax (и a!) на него по прежнему указывают, т.е. - в никуда.
               // Пользоваться ими ни в функции, ни в майне нельзя
}

Объяснение кода листинга программы

  1. В функции main() объявлены две переменные: a и size. Переменная a является указателем на int, а переменная size - на int.
  2. В функции main() вызывается функция f(), передавая ей в качестве аргументов указатель на переменную a и указатель на переменную size.
  3. В функции f() происходит следующее:
    • Объявляется переменная ax, которая является указателем на int и инициализируется значением переменной a.
    • Значение переменной ax изменяется на результат вызова функции malloc().
    • Значение переменной ax изменяется на результат вызова функции realloc().
    • Вызывается функция free(), передавая ей в качестве аргумента переменную ax.
    • После вызова функции free() значение переменной ax (и переменной a в функции main()) не меняется, поскольку они оба указывают на ту же область памяти.
  4. В конце функции main() есть пропущенное место, которое обозначено троеточием (...). Здесь могут находиться другие действия, которые не были указаны в вопросе.

Оцени полезность:

8   голосов , оценка 4.375 из 5
Похожие ответы