2015-04-30 3 views
0
Consider the following functions 
void alloco(int **ppa) 
{ 
    int i; 
    printf("inside alloco %d\n",ppa); /*this function allocates and fills 20 * sizeof(int) bytes */ 
    *ppa = (int *)malloc(20 * sizeof(int)); 
    /*fill all 20 * sizeof(int) bytes */ 
} 

int main() 
{ 
    int *app = NULL; 
    int i; 
    printf("inside main\n"); 
    alloco(&app); 
    for(i=0;i<20;i++) /*ISSUE::how will i know to traverse only 20 indexes?*/ 
    printf("app[%d] = %d \n", i, app[i]); 
    return(0); 
} 

В основном, как main() узнает количество байтов для перемещения памяти i.e, выделенной функцией alloco(). Есть ли какой-нибудь разделитель, такой как NULL в массивах символов?Конец целочисленного/структурного массива?

+0

Если вам действительно нужно это сделать, не передавая размер, то вам нужно заполнить разделитель самостоятельно или вам нужно полагаться на конкретную реализацию платформы malloc для доступа к заголовку. –

+0

C- «строки» ('char' array) заканчиваются' NUL' aka 'null' aka' '\ 0'', но, конечно же, не 'NULL', последнее - это нечто иное. – alk

+0

Если этот шаблон встречается часто, вы можете захотеть иметь структуру, отслеживающую длину данных, на которые указывает ее второй элемент, указатель. Или вы используете язык, который имеет эту структуру в своей стандартной библиотеке ;-) –

ответ

2

Это не возможно, вам нужно сохранить это значение где-то, например, вы могли бы сделать это,

void alloco(int **ppa, int count) 
{ 
    int i; 

    printf("inside alloco %d\n",ppa); 
    *ppa = malloc(count * sizeof(int)); 
    if (*ppa == NULL) 
     return; 
    for (i = 0 ; i < count ; ++i) 
     /* fill it here. */ 
} 

int main() 
{ 
    int *app; 
    int i; 
    int count; 

    count = 20; 
    app = NULL; 
    printf("Inside main\n"); 
    alloco(&app, count); 
    if (app == NULL) 
     return -1;  
    for (i = 0 ; i < count ; i++) 
     printf("app[%d] = %d \n", i, app[i]); 
    /* done with `app' */ 
    free(app); 
    return 0; 
} 

многие другие комбинации могли бы работать, например

int alloco(int **ppa) 
{ 
    int i; 

    printf("inside alloco %d\n",ppa); 
    *ppa = malloc(20 * sizeof(int)); 
    if (*ppa == NULL) 
     return; 
    for (i = 0 ; i < count ; ++i) 
     /* fill it here. */ 
    return 20; 
} 

int main() 
{ 
    int *app; 
    int i; 
    int count; 

    printf("Inside main\n"); 

    app = NULL; 
    count = alloco(&app); 
    if (app == NULL) 
     return -1;  
    for (i = 0 ; i < count ; i++) 
     printf("app[%d] = %d \n", i, app[i]); 
    /* done with `app' */ 
    free(app); 
    return 0; 
} 

Но я лично дон Это не так, потому что если будет фиксированное число целых чисел, то не стоит использовать malloc(),

int main() 
{ 
    int app[20]; 
    int i; 

    printf("Inside main\n");  
    for (i = 0 ; i < sizeof(app)/sizeof(app[0]) ; i++) 
     printf("app[%d] = %d \n", i, app[i]); 
    return 0; 
} 
+0

вы уверены? если это аргумент «count», то то, что вы использовали там, должно быть определено alloco в моем случае, поэтому мне нужно передать по ссылке count для функции alloco, правильно? – Coder

+0

Не обязательно, я думаю, вы пытаетесь что-то сделать с идеями с какого-то другого языка программирования, можете ли вы объяснить, почему вы хотите это сделать? Посмотрите второе решение, которое я предложил, очень плохой дизайн, чтобы определить размер буфера в функции распределителя, это не имеет большого смысла. –

+0

Нет, ничего подобного, мое требование - это что-то вроде этого: main() дает alloco() указатель NULL, alloco должен заполнить это (на основе вывода некоторых других функций) и сообщить main() до где читать (если вы правы). – Coder

1

Есть ли разделитель, такой как NUL L в массивах символов?

Если вы определите один, то да.

Это, однако, возможно только в том случае, если вашему прецеденту не нужны все возможные целочисленные значения.

Если, например, вам нужны только положительные значения, в том числе 0, вы можете определить значение -1 как маркер «End-of-Array».

Затем вы выделите еще один элемент массиву, который вам нужен, и назначьте -1 этому дополнительному очень последнему элементу массива.

Пример:

#include <stdlib.h> /* for malloc */ 
#include <errno.h> /* for errno */ 

#define EOA (-1) 

int array_allocate(int ** ppi) 
{ 
    int result = 0; 

    if (NULL = ppi) 
    { 
    result = -1; 
    errno = EINVAL; 
    } 
    else 
    { 
    size_t number_of_elements = ...; /* Assign some positive value here. */ 

    *ppi = malloc((number_of_elements + 1) * sizeof ** ppi); 
    if (NULL == *ppi) 
    { 
     result = -1; 
    } 
    else 
    { 
     (*ppi)[number_of_elements] = EOA; 
    } 
    } 

    return result; 
} 

ssize_t array_number_of_elements(int * pi) 
{ 
    int result = 0; 

    if (NULL == pi) 
    { 
    result = -1; 
    errno = EINVAL; 
    } 
    else 
    { 
    int * pi_tmp = pi; 
    while (EOA != *pi_tmp) 
    { 
     ++pi_tmp; 
    } 

    result = pi_tmp - pi; 
    } 

    return result; 
} 

Используйте это так:

#include <stdlib.h> /* for size_t and ssize_t */ 
#include <stdio.h> /* for printf and perror */ 

int array_allocate(int **); 
ssize_t array_number_of_elements(int *); 

int main(void) 
{ 
    int result = EXIT_SUCCESS; 
    int * pi = NULL; 

    if (-1 == array_allocate(&pi)) 
    { 
    result = EXIT_FAILURE; 
    perror("array_allocate() failed"); 
    } 
    else 
    { 
    ssize_t result_number_of_elements = array_number_of_elements(pi); 
    if (-1 == result_number_of_elements) 
    { 
     result = EXIT_FAILURE; 
     perror("array_number_of_elements() failed"); 
    } 
    else 
    { 
     size_t number_of_elements = result_number_of_elements; 
     printf("The number of array's elements is %zu.\n", 
     number_of_elements); 
    } 
    } 

    free(pi); /* Clean up. */ 

    return result; 
} 
0

Он принимает став 3-Star программатор

Вы можете легко выделить некоторое фиксированное число элементов (меньше максимального) в функции без пропускания количества элементов между функции вызывающего абонента и вызываемого абонента. Тем не менее, требуется создание массива указателей указателям на тип How/Why? По существу, вы обрабатываете свой массив как строку с завершающим нулем, изначально выделяя все указатели для ввода внутри массива NULL и выделяя при этом пространство для них по мере необходимости. (выделение с помощью calloc делает это привязкой). Когда массив используется обратно в вызывающем, он позволяет выполнять итерацию по всем значениям, пока вы не достигнете первого нулевого указателя.

Теперь предоставлен,

просто передавая указатель размера в качестве дополнительного аргумента для вашей функции имеет гораздо больше смысла [1]

и устраняет необходимость в трёх- но для целей примера, пользуйтесь 3-Star Программист для заказа:

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

#define INITSZ 21 

void alloco (int ***ppa) 
{ 
    printf("inside %s\n", __func__); 

    int i = 0; 

    /* allocate 21 pointers-to-int */ 
    if (!(*ppa = calloc (INITSZ, sizeof **ppa))) { 
     fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__); 
     exit (EXIT_FAILURE); 
    } 

    /* allocate/fill 20 values (or anything less than 21) */ 
    for (i = 0; i < INITSZ - 1; i++) { 
     if (!((*ppa)[i] = calloc (1, sizeof ***ppa))) { 
      fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__); 
      exit (EXIT_FAILURE); 
     } 
     *((*ppa)[i]) = i * 2; 
    } 
} 

int main() 
{ 
    int **app = NULL; 
    int i = 0; 

    printf ("inside main\n"); 
    alloco (&app); 

    /*ISSUE::how will i know to traverse only 20 indexes?*/ 

    while (app[i]) { 
     printf("app[%d] = %d \n", i, *(app[i])); 
     i++; 
    } 

    return(0); 
} 

Использование/выход

$ ./bin/alloc_array+1 
inside main 
inside alloco 
app[0] = 0 
app[1] = 2 
app[2] = 4 
app[3] = 6 
app[4] = 8 
app[5] = 10 
app[6] = 12 
app[7] = 14 
app[8] = 16 
app[9] = 18 
app[10] = 20 
app[11] = 22 
app[12] = 24 
app[13] = 26 
app[14] = 28 
app[15] = 30 
app[16] = 32 
app[17] = 34 
app[18] = 36 
app[19] = 38 

сноска [1]: курсив в цитате для ясности, что это решение было предназначено, чтобы показать, что было возможно, не то, что было наиболее эффективным и наиболее практичным.

+0

Вы знаете, что этот подход (по крайней мере, на 64-битной системе) занимает 3 раза больше памяти, чем при использовании линейного массива. – alk

+0

Две ошибки здесь: 1st: This: '(** ppa) [i] = i * 2;' будет '* ((* ppa) [i]) = i * 2';' и 2nd this 'printf ("app [% d] = ... (* приложение) [i]);' будет 'printf (" app [% d] = ... * (приложение [i])); ' – alk

+0

Я ценю ошибку исправления. Что касается памяти, это не было предназначено как кандидат на эффективность, это подразумевалось как «непрактичное решение точных вопросов» **. Вот почему он явно квалифицировался с ** передачей указателя на размер, поскольку дополнительный аргумент вашей функции имеет гораздо больший смысл **. Благодарю. –

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

  • Нет связанных вопросов^_^