Передача переменных указателя через функции в C - PullRequest
1 голос
/ 10 марта 2011

У меня здесь странное поведение. Любая помощь будет великолепна.

Я начинаю так:

   int *event_positions = (int *) malloc(1 * sizeof(int)); // let us start with 1 and then add more within the method. This should continue until we have all the flags we want.  
   int number_of_flags = event_extractor(vocal_data, size, event_positions);


 // HERE I WOULD LIKE TO USE THE VALUES OF event_positions BUT THE ARE WEIRD I.E. THEY DON'T MATCH THE VALUES BEING PRINTED IN THE LAST METHOD. 

Затем средство извлечения событий передает переменную другому методу. Упрощенно это выглядит так:

int event_extractor (int *audio_samples, unsigned int size_of_audio ,int *event_flags)
{

    int number_of_flags = apply_threshold (lopass_samples, length, event_flags);
    // PRINT ARRAY event_flags HERE 
    // VALUES ARE INCORRECT AND WEIRD

}

Последний метод:

int apply_threshold (int *audio_samples, unsigned int size_of_audio, int *event_flags)
{
// DO SOME STUFF HERE.
// PRINT THE ARRAY WHICH SHOW THE  CORRECT VALUES.



}

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


РЕДАКТИРОВАТЬ 1

Первый файл:

   int *event_positions = (int *) malloc(1 * sizeof(int)); // let us start with 1 and then add more within the method. This should continue until we have all the flags we want.  
   int number_of_flags = event_extractor(vocal_data, size, event_positions);

Второй файл:

  int apply_threshold (int *audio_samples, unsigned int size_of_audio, int *event_flags)
{


int flag = 0; // this will be the number of flags that I have 
bool run = true; // this will make sure that a minimum amount of time passes before I grab another flag. It's a guard.
int counter = 0; // this is the counter for the above guard. 





printf("\n\nCURRENT MINIMUM TIME:  20100 SAMPLES \n\n");

// event_flags[0] = 1; // this first one is a dud. within the loop we will automatically start adding flags


int threshold = calculate_threshold_value(audio_samples, size_of_audio);

printf("\n\n this is the threshold %d \n\n", threshold);

int length = (int)size_of_audio;

for (int i = 0; i < length; i++) 
{

    if (audio_samples[i] > threshold  && run) 
    {

        // ** is this realloc working ?
        event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1)); // reallocate the size of the array
        event_flags[flag] = i;
        // printf("FLAG CREATED! %i\n ", i);
        printf("EVENT FLAG %i  %i\n",flag, event_flags[flag] );
        flag++;
        run = false;

    }   

    if (!run) {
        counter++;
        if (counter > 20100) { // hardcode minimum size for now. 
            counter = 0;
            run=true;
        }
    }

}

printf("\n\n\n NUMBER OF EVENTS --- %d\n", flag);

for (int i = 0; i < flag; i++) {
    printf("FLAG %i  -- %d\n", i, event_flags[i]);
}



printf("\nFIVE samples before and after my second flag: \n 0 should indicate a reach in the threshold\n");

for (int i = 0; i <10 ; i++) {
    printf("VOCAL SAMPLE %i  %i \n", i-5,audio_samples[event_flags[1]+i-5] );
}


return flag;



}

РЕДАКТИРОВАТЬ 2

Я обновил свой код в соответствии с моделью Эрика. Мой цикл теперь выглядит так

    if (audio_samples[i] > threshold  && run) 
    {

        // ** is this realloc working ?
        // event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1));
        *event_flags = (int*)realloc(*event_flags, sizeof(int) * (flag+1)); // reallocate the size of the array
        *event_flags[flag] = i;
        // printf("FLAG CREATED! %i\n ", i);
        printf("EVENT FLAG %i  %i\n",flag, *event_flags[flag] );
        flag++;
        run = false;

    }   

А теперь я получаю сообщение об ошибке, похожее на это. Есть идеи? enter image description here

Ответы [ 2 ]

3 голосов
/ 10 марта 2011

Перераспределяете ли вы event_flags в apply_threshold? Если это так, вам нужно позволить вызывающей стороне получить обновленный указатель обратно.

Что-то вроде:

int apply_threshold (int *audio_samples, unsigned int size_of_audio, int **event_flags) {
    *event_flags = realloc ...
}

...

int number_of_flags = apply_threshold (lopass_samples, length, &event_flags);

РЕДАКТИРОВАТЬ: В ответ на обновленный вопрос:

event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1)); // reallocate the size of the array

Это изменяет локальную копию указателя event_flags. Звонящий не увидит изменения. Используйте метод, который я описал выше.

EDIT2: более подробный образец.

void foo(int * v) {
    v = 0; // The local copy of main's myvar is now 0. main's actual myvar is unchanged
}

void bar(int ** v) {
    *v = 0; // Main's myvar is now 0, we have a pointer to it and can modify it.
}

int main() {
    int * myvar = (int *) malloc(1); // Allocate 1 byte and make myvar point at this byte.
    foo(myvar); // Call foo, passing a *copy of* myvar, which also points at the allocated byte
    bar(&myvar); // Call bar, passing a *pointer to* myvar, which again points to the allocated byte
}

РЕДАКТИРОВАТЬ3: В ответ на новый вопрос.

Является ли ваша "длина" числом байтов или числом байтов ? Вы рассматриваете это как число целых, что может привести к вашей ошибке, если это действительно число байтов.

0 голосов
/ 10 марта 2011

Вам нужно передать указатель на указатель или ссылку на указатель. Realloc может перемещать вашу память в другую позицию, и вызывающая сторона не заметит.

  realloc() changes the size of the memory block pointed to by ptr to size bytes.  The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized.  If ptr is NULL, then  the
   call  is  equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr).  Unless ptr is NULL, it must have been returned by an earlier call to mal‐

loc (), calloc () или realloc (). Если область, на которую указывает указатель, была перемещена, выполняется свободное (ptr) .

...