2013-05-23 4 views
0

Я создал общую матричную структуру, как это:Generic матрица: как передать тип в качестве аргумента функции

typedef struct mat_t { 
    /** 
    * \brief matrix structure 
    */ 
    unsigned int c, l; 
    void **matrice; 
}* mat; 

Моя проблема заключается, чтобы узнать, как выделить память для матрицы, так как она может содержать комплексные числа, числа с плавающей запятой или другие ... Таким образом, я хочу знать, как передать тип аргументу функции для памяти распределения.

mat allocate_mat(unsigned int l, unsigned int c, **<type>**) 

Возможно, следует использовать макрос define для этой функции?

+1

Почему просто не проходящее размер типа? Например, 'mat allocate_mat (unsigned int l, unsigned int c, unsigned int size)' и затем вызывает его следующим образом: 'allocate_mat (10,5, sizeof (float))' – JBL

ответ

0

Вы можете передать размер матричного элемента:

mat allocate_mat(unsigned int l, unsigned int c, unsigned int size_of_matrix_element) 
+0

Да, но мне нужна два malloc для моей матрицы. Итак, мне нужно два sizeof(), один для указателя элемента и один для элемента. Как я могу справиться с этим, если просто передать размер элемента матрицы? – user2412542

+1

@ user2412542 Все указатели имеют одинаковый размер; например 'sizeof (void *)' расскажет вам, что это такое. –

+0

@MattPhillips Хорошо, я думал, что сделать malloc с sizeof (void *) будет ошибкой, но это кажется хорошим! Thks – user2412542

1

Может быть, я должен использовать определить макрос для этой функции?

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

#define allocate_mat(MAT_L, MAT_C, MAT_TYPE) allocate_mat_sz(MAT_L, MAT_C, sizeof(MAT_TYPE)) 
mat allocate_mat_sz (unsigned l, unsigned c, size_t size); 
+0

Меня постоянно удивляет нетерпимость к другому способу делать вещи. Это так скучно. – jxh

+0

Это, конечно, хромой, что у вас есть нисходящий звук без объяснения причин. Возможно, потому, что вы существенно меняете язык, например. 'allocate_mat (2,3, float);' который компилируется только с вашим макросом. Интересный подход. –

+0

@MattPhillips: Не похоже, что в самом стандарте C нет прецедента. 'va_arg()' приходит на ум. – jxh

1

Задача 1: странные имена переменных. Что означает l и c? «Линии», «счет»? В C нет ничего, что препятствовало бы вам использовать полные слова в качестве имен переменных ...

Проблема 2: вы, скорее всего, используете ложный двумерный массив с указателем на указатель, что приводит к кучке фиаско фрагментации. Он не только замедляется и приводит к фрагментации кучи, но также не может использоваться с фундаментальными функциями C, такими как memset(), memcpy(). Выделите настоящий 2D-массив, а в соседней памяти.

Задача 3: Почему у вас есть * mat в конце структуры typedef? Это не имеет никакого смысла.

Вот базовая реализация динамической матрицы, используя общие программирования C:

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

typedef struct mat_t 
{ 
    void** data; 
    size_t row_n; 
    size_t col_n; 
    size_t obj_size; 
} matrix_t; 


bool matrix_init (matrix_t* mat, 
        size_t row_n, 
        size_t col_n, 
        size_t obj_size) 
{ 
    mat->row_n = row_n; 
    mat->col_n = col_n; 
    mat->obj_size = obj_size; 

    mat->data = calloc(row_n * col_n, obj_size); 

    return mat->data != NULL; 
} 


void matrix_free (matrix_t* mat) 
{ 
    free(mat); 
} 


void matrix_set (matrix_t* mat, 
       size_t x, 
       size_t y, 
       void*  val) 
{ 
    size_t data_offset = y * mat->row_n * mat->obj_size + 
         x * mat->obj_size; 

    memcpy (mat->data + data_offset, 
      val, 
      mat->obj_size); 
} 


void* matrix_get (const matrix_t* mat, 
        size_t x, 
        size_t y) 
{ 
    size_t data_offset = y * mat->row_n * mat->obj_size + 
         x * mat->obj_size; 

    return mat->data + data_offset; 
} 


int main() 
{ 
    matrix_t mat; 
    const int ROWS=3; 
    const int COLS=2; 

    // allocate memory 
    matrix_init(&mat, ROWS, COLS, sizeof(int)); 


    // fill memory with data 1,2,3... 
    int count =0; 
    for(int row=0; row<ROWS; row++) 
    { 
    for(int col=0; col<COLS; col++) 
    { 
     count++; 
     matrix_set (&mat, row, col, &count); 
    } 
    } 

    // print the matrix 
    for(int row=0; row<ROWS; row++) 
    { 
    printf("[ "); 
    for(int col=0; col<COLS; col++) 
    { 
     printf("%d ", *(int*)matrix_get(&mat, row, col)); 
    } 
    printf("]\n"); 
    } 

    matrix_free(&mat); 
    return 0; 
} 
+0

Что значит «не имеет никакого смысла»? В этом суть typedef! 'typedef struct mat_t {/ * matrix */unsigned int c, l; void ** matrice} * mat; 'говорит, 'вот что выглядит' struct mat_t', теперь создайте тип 'mat', который будет представлять собой указатель на структуру типа' struct mat_t'. –

+0

@ ElchononEdelson То, что я имею в виду, это не имеет смысла скрывать декларацию указателя за typedef, особенно в этом случае. Это только делает код уязвимым и трудночитаемым. – Lundin

+0

Ах. Это никоим образом не было видно из того, как вы это сказали. Однако, независимо от того, как вы думаете, что он делает код уязвимым и трудночитаемым, мне кажется, что это довольно распространенная идиома. –

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