Проблема с передачей указателя на функцию в C

#c #pointers

#c #указатели

Вопрос:

Это одна из тех раздражающих вещей, когда вы знаете, что ответ прост, но вы просто не можете его увидеть.

printf Инструкция в AllocIntArray показывает, что arrayPtr ячейка памяти назначается правильно, однако, когда выполняется printf инструкция в main, она показывает, что arrayB значение по-прежнему равно NULL .

Может кто-нибудь показать мне, что я делаю неправильно при передаче в arrayB в AllocIntArray ?

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

void AllocIntArray(int *arrayPtr, int numElements);

int main()
{
   int *arrayB = NULL;

   AllocIntArray(arrayB, 10);
   printf("Pointer: %pn", arrayB);

   free(arrayB);

   getchar();
   return EXIT_SUCCESS;
}

void AllocIntArray(int *arrayPtr, int numElements)
{
   arrayPtr = (int *)malloc(sizeof(int) * numElements);
   printf("Pointer: %pn", arrayPtr);

   if(arrayPtr == NULL)
   {
      fprintf(stderr, "nError allocating memory using malloc");
      exit(EXIT_FAILURE);
   }
}
  

Комментарии:

1. Я думаю, что ваш arrayPtr arrayPtr должен быть от указателя к указателю, чтобы иметь возможность выделять и видеть за пределами области действия функции. так что int **arrayPtr

Ответ №1:

Передайте двойной указатель.

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

void AllocIntArray(int **arrayPtr, int numElements);

int main()
{
   int *arrayB = NULL;

   AllocIntArray(amp;arrayB, 10);
   printf("Pointer: %pn", arrayB);

   free(arrayB);

   getchar();
   return EXIT_SUCCESS;
}

void AllocIntArray(int **arrayPtr, int numElements)
{
   *arrayPtr = malloc(sizeof(int) * numElements);
   printf("Pointer: %pn", *arrayPtr);

   if(*arrayPtr == NULL)
   {
      fprintf(stderr, "nError allocating memory using malloc");
      exit(EXIT_FAILURE);
   }
}
  

Комментарии:

1. 1, но я колебался — пожалуйста, не приводите возвращаемые значения malloc.

2. @paxdiablo, разве это не просто вопрос предпочтений программиста?

3. @Chris, приведение его может скрыть определенные ошибки и предупреждения от компилятора, что усложнит вашу жизнь. Например: faq.cprogramming.com/cgi-bin /…

4. При программировании никогда не делайте вещей, причины которых вам неизвестны. Приведение результата из malloc является одной из таких вещей. Большую часть времени люди приводят его, не задумываясь, потому что их компилятор C выдает предупреждение… то есть они используют неправильный компилятор и скрывают это за явным приведением типов.

Ответ №2:

Это потому, что arrayB передается AllocIntArray по значению. Либо передайте его по ссылке (с помощью указателя на указатель), или, что лучше, верните его из AllocIntArray :

 int *AllocIntArray(int numElements)
{
   int *arrayPtr = malloc(sizeof(int) * numElements);
   printf("Pointer: %pn", arrayPtr);

   if(arrayPtr == NULL)
   {
      fprintf(stderr, "nError allocating memory using malloc");
      exit(EXIT_FAILURE);
   }
   return arrayPtr;
}
  

Комментарии:

1. Еще один хороший способ сделать это (особенно, если это позволяет избежать проблем, возникающих у большинства новичков с косвенными указателями. Но, опять же, почему вы возвращаете значение из malloc ?

2. @paxdiablo: Я скопировал код операционной системы и внес в него минимальные изменения, чтобы продемонстрировать свои намерения. Также удалено malloc приведение возврата.

Ответ №3:

Вам нужно немного освежить в памяти передачу параметров функциям.

Указатель, который вы отправляете в AllocIntArray, копируется в arrayPtr, строка

    arrayPtr = (int *)malloc(sizeof(int) * numElements);
  

присваивает значение копии, а не исходной переменной, и поэтому исходная переменная по-прежнему указывает в никуда.

Первое решение, которое приходит на ум, — отправить указатель на этот указатель, но я думаю, вам лучше сделать некоторые общие уточнения по вопросу передачи параметров, прежде чем идти намного дальше.

Комментарии:

1. Я просто пока не делал много упражнений с указателем на указатель в своей классной работе, поэтому использование его здесь ускользнуло от меня. Однажды увидев это, это приобретает смысл.

Ответ №4:

arrayPtr является указателем, и указатель передается по значению параметру. AllocIntArray может изменить свою версию arrayPtr , но изменения не будут замечены main() .

(Редактировать: если вы используете C ) изменение подписи для AllocIntArray изменения типа arrayPtr на ссылку должно решить вашу проблему.

 void AllocIntArray(int *amp;arrayPtr, int numElements)
  

Комментарии:

1. WTF является *amp; ? Вам лучше не пытаться испортить мой прекрасный язык C своими проделками на C 🙂

2. Ааа… извините. Пометьте мой ответ ‘c ‘.

Ответ №5:

Основная проблема здесь в том, что вы передаете arrayB в AllocIntArray функцию как переданное по значению .В AllocIntArray он выделяет память правильно и arrayptr является допустимым, но в main функции это не та память, которую вы ожидаете. Это базовая концепция программирования на C, и вы можете проверить, добавив print в обе функции.

ПРИМЕР: Я делюсь разницей между проблемой и случаем успеха в приведенном ниже примере.

 /*Code with passed by value as a parameter*/ 
#include<stdio.h>
#include<stdlib.h>
void AllocateIntarray(int *arrayptr,int numElements)
{
     arrayptr = (int*) malloc(sizeof(int)*numElements);
     printf("Inside _func_AllocateIntarray_pointer:%pn",arrayptr);

     if(arrayptr == NULL)
     {
         printf("ERR_MEM_ALLOCATION_FAILED:n");
     }
}

int main()
{
     int *arrayB = NULL;
     AllocateIntarray(arrayB,10);
     printf("Inside _func_mainPointer:%pn",arrayB);

     free(arrayB);
     return 0;
 }
/*Output :
 Inside _func_AllocateIntarray_pointer:0x55be51f96260
 Inside _func_mainPointer:(nil)*/
  

Код с передачей по ссылке и использованием двойного указателя .

 #include<stdio.h>
#include<stdlib.h>
void AllocateIntarray(int **arrayptr,int numElements)
{
     *arrayptr =  malloc(sizeof(int)*numElements);
     printf("Inside _func_AllocateIntarray_pointer:%pn",*arrayptr);

     if(*arrayptr == NULL)
     {
          printf("ERR_MEM_ALLOCATION_FAILED:n");
     }
 }
 int main()
 {
     int *arrayB = NULL;
     AllocateIntarray(amp;arrayB,10);
     printf("Inside _func_mainPointer:%pn",arrayB);

     free(arrayB);
     return 0;
  }
  /*Output :
    Inside _func_AllocateIntarray_pointer:0x562bacd1f260
    Inside _func_mainPointer:0x562bacd1f260*/