2013-05-18 2 views
-2

У меня трудные времена, пытаясь передать ссылку двойного указателя на функцию. у меня есть это:Передача двойного указателя на функцию в качестве ссылки - c

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

#define MAX_ROWS 2 
#define MAX_COLS 2 

int main(void){ 
    int i=0,lenght=0,maxColumns=0,j=0,k=0,maxRows=0,maxColumns2=0; 
    int **columnVect; 
     /*lengthOfPtr gives me the columns that i need. */ 
    if((lenght=(lengthOfPtr(ptrMessage)))<=3){ 
     maxColumns=1; 
     maxColumns2=2; 
    }else{ 
     maxColumns=lenght/2; 
     maxColumns2=maxColumns; 
    } 
     /* Allocating Memory for the double pointer. */ 
    columnVect=malloc(maxColumns2 * sizeof(int*)); 
    if(columnVect == NULL){ 
     fprintf(stderr, "Memory error.\n"); 
     exit(0); 
    } 

    for(i = 0; i < maxColumns2; i++){ 
     columnVect[i] = malloc(maxRows * sizeof(int)); 
     if(columnVect[i] == NULL){ 
      fprintf(stderr, "Memory error.\n"); 
      exit(0); 
     } 
    } 

    // Do something that fills columnVect[i][j] 

     /* Passing the double pointer to messageVector */ 
    messageVector(&columnVect,maxColumns); 
return 0; 
} 


int messageVector(int ***columnVect,int maxColumns){ 
     /* Allocating Memory for the triple pointer. */ 
    columnVect=(int ***)malloc(sizeof(int **)); 

    //Do something here . . . 

return messageVector; 
} 

Если я запустить программу дает мне: (lldb)

В:

3 старт libdyld.dylib`start: 0x7fff88b447e0: NOP

Кто-нибудь мог сказать мне, как это сделать правильно? Благодаря!

+0

Что такое функция 'messageVector', вы хотите изменить двойной указатель, выделенный ранее? Если нет, вам не нужно выделять его. – Rohan

+0

Да, возможно, кто-нибудь может сказать вам решение, если код был читабельным и достаточно маленьким. –

+0

Цель состоит в том, чтобы умножить возвращаемое значение. – unixeO

ответ

1

Хорошо, хотя я не совсем понимаю, что вы пытаетесь выполнить с помощью функции messageVector, я думаю, что ваш вопрос является законным, поэтому я постараюсь дать вам некоторое представление.

Прежде всего, есть еще одна проблема с кодом, который вы представили в функции main. Если malloc сбой при назначении строк maxColumns2, вы выходите без free любых ранее выделенных строк.

Обратите внимание, что я намеренно поменял текст maxColumns2 и maxRows, потому что в общем контексте он имеет немного больше смысла. По идее, вы начинаете с выделения строк указателей int, а затем для каждой строки вы выделяете столбцы int.

Таким образом, вы можете попробовать что-то вроде этого вместо того, чтобы ...

/* Allocating Memory for the double pointer. */ 

columnVect = malloc(maxRows * sizeof(int *)); 
if (columnVect == NULL){ 
    fputs("Memory error.\n", stderr); 
    exit(0); 
} 

for (int i=0; i < maxRows; i++) 
{ 
    columnVect[i] = malloc(maxColumns2 * sizeof(int)); 
    if (columnVect[i] == NULL) 
    { 
     fputs("Memory error.\n", stderr); 
     for (int j = i-1; j > -1; j--) 
      free(columnVect[j]); 
     free(columnVect); 
     columnVect = NULL; 
     exit(0); 
    } 
} 

Внутреннего цикла (с помощью j счетчика) идет от последней успешно выделенной строки к 1-ому, free ИНГАМ их на путь. После этого columnsVect также получает free 'ed (то есть память зарезервирована для указателей int перед внешним контуром), и она установлена ​​в NULL.

Возможно, я, вероятно, задираю здесь, поскольку большинство современных операционных систем освободят любую память, выделенную вашей программой после ее завершения, но это хорошая привычка всегда освобождать выделенную память. С одной стороны, это помогает при отладке вашего кода. Он также защищает вас от создания утечек памяти в будущем, если вам нужно внедрить свой текущий код в более крупный проект (например, в библиотеку).

Теперь, передавая ссылку двойного указателя на функцию, хороший и простой пример imho будет функцией, которая освобождает память, зарезервированную для этого указателя, и устанавливает указатель на NULL. Что-то вдоль этих линий:

void free_int2d(int ***int2d, int nrows) 
{ 
    int i; 

    if (nrows < 1) { 
     printf("*** warning: %s() failed, no memory freed\n", __func__); 
     return; 
    } 
    if (!int2d || !*int2d) 
     return; 

    for (i=0; i < nrows; i++) { 
     if ((*int2d)[i]) 
      free((*int2d)[i]); 
    } 

    *int2d = NULL; 
} 

Надеюсь, это говорит само за себя, но только в том случае, позвольте мне отметить несколько вещей.

Главное, чтобы написать *int2d всякий раз, когда вы хотите выразить свой оригинальный двойной указатель внутри функции (то есть строки указателей int).

Другой - то, что, если вы хотите выразить i 'th ряд, вы пишете (*int2d)[i]. Вы должны явно заключить 1-е разыменование в круглых скобках ... 2-я разыменованная операция выполняется неявно через нотацию [].

Наконец, в качестве примера передачи по ссылке двойной указатель на эту функцию, здесь внутренний цикл исходного кода, переписанного с помощью этой функции free_int2 ...

for (int i=0; i < maxRows; i++) 
{ 
    columnVect[i] = malloc(maxColumns2 * sizeof(int)); 
    if (columnVect[i] == NULL) 
    { 
     fputs("Memory error.\n", stderr); 
     free_int2d(&columnVect, i); 
     exit(0); 
    } 
} 

Это существенно упрощается, таким образом, более читаемым. free_2d(&columnVect, maxRows) также должен быть вызван по успешному завершению программы (по причинам, описанным выше).

EDIT

Из соображений производительности, вы можете рассмотреть вопрос предварительного выделения буфера для malloc ИНГ столбцов, и перераспределить его по мере необходимости (возможно, путем удвоения его размера). Но это дает немного более сложный код.

Смежные вопросы