Как я могу передать «Тип» в качестве аргумента функции в c? - PullRequest
0 голосов
/ 21 мая 2018

Я хочу написать обобщенную функцию (например, функцию, которая получает массив с типом 'void **' и делает что-то с этим массивом), тогда эта функция получит тип элемента (в примере это будетбыть типом любого элемента в массиве) в качестве аргумента.

Могу ли я сделать это в c?


Например:
Я хочу написать функцию, которая получает массив (в типе void**) и инициализирует этот массив некоторым случайным образом.
что означает «каким-то случайным образом» - например, функция, которая получает в качестве аргументов: массив (в типе void **), тип любого элемента в массиве , индекс (в типе int) иинициализировать эту ячейку.

Ответы [ 4 ]

0 голосов
/ 21 мая 2018

Другим решением может быть определение перечисления для представления типа:

#include "stdio.h"

typedef enum {
    TYPE_INT,
    TYPE_CHAR,
    TYPE_STRING
} type_id;

int print(type_id type, void *data) {
    switch (type) {
    case TYPE_INT:
        // Do something with data as int
        printf("%d\n", * (int *)data);
        break;
    case TYPE_CHAR:
        // Do something with data as char
        printf("%c\n", * (char *)data);
        break;
    case TYPE_STRING:
        // Do something with data as string
        printf("%s\n", (char *)data);
        break;
    }
}

int main() {
    int a = 5;
    char b = 'a';
    char *c = "string";

    print(TYPE_INT, &a);
    print(TYPE_CHAR, &b);
    print(TYPE_STRING, c);

    return 0;
}

Мне нравится предложение Лундина больше, поскольку оно обеспечивает безопасность типов.

0 голосов
/ 21 мая 2018

Вы не передаете «тип».C не имеет встроенного способа кодирования и декодирования информации о типе во время выполнения.Функция, работающая с объектами, должна знать тип статически.Если вы абсолютно намерены работать с указателями на void, вам необходимо делегировать функцию, которая знает информацию о типе.Это можно сделать с помощью обратного вызова.Например, стандартная библиотечная функция qsort принимает обратный вызов для сравнения значений объектов:

void qsort( void *ptr, size_t count, size_t size,
            int (*comp)(const void *, const void *) );

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

0 голосов
/ 21 мая 2018

Вот пример для некоторых макросов.

func.h

#ifndef FUNC_H
#define FUNC_H

#define add(a, b, typename) functionAdd##typename(a,b)

/* function declarations */
#define declared(typename) \
typename functionAdd##typename(typename, typename)

declared(int);
declared(float);

#endif

func.c

#include "func.h"

/* function code */
#define functionAdd(a, b, typename) \
typename functionAdd##typename(typename a, typename b){ \
    return a+b; \
}

/* function bodies (definitions) */
functionAdd(a, b, int)
functionAdd(a, b, float)

main.c

#include <stdio.h>
#include "func.h"

int main()
{
    int x1 = add(1, 2, int);
    float x2 = add(3.0, 4.0, float);
    printf("%d %f\n", x1, x2);  
    return 0;
}
0 голосов
/ 21 мая 2018

Это возможно только в том случае, если у вас есть стандартный компилятор C, и в этом случае вы можете использовать для этой цели ключевое слово _Generic.Вы должны написать другую функцию для поддерживаемого типа.

#include <stdio.h>

#define func(x) _Generic((x), int: func_int, char: func_char)(x);

void func_int (int x)
{
  printf("%s\t%d\n", __func__, x);
}

void func_char (char x)
{
  printf("%s\t%c\n", __func__, x);
}


int main(void)
{
  int i = 5;
  char c = 'A';

  func(i);
  func(c);
}

Вывод:

func_int        5
func_char       A
...