C Пустой вопрос об указателе

У меня есть функция grep в C (встроенное программирование), который берет пустой указатель в качестве параметра. функция должна смочь обработать различные виды типов переменных как символы ints и longs. Как я могу кодировать функцию, таким образом, она может выяснить отдельно, какая переменная я являюсь передающим?? Я не знаю, возможно ли это.спасибо

т.е.


void grep( void *t ) 
{ 
   if( t == char ) 
   { 
      do this 
   } 
   if( t == int ) 
   { 
      do that  
   }  
   ... 
}
5
задан jramirez 7 July 2010 в 20:52
поделиться

12 ответов

Это невозможно сделать с какой-либо точностью. Например, целое число в 4 байта можно легко интерпретировать как строку. Например, строка с нулевым окончанием "ABC" будет равна целочисленному значению 1094861568 (в зависимости от порядка байт).

14
ответ дан 18 December 2019 в 05:28
поделиться

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

5
ответ дан 18 December 2019 в 05:28
поделиться

Указатель пустоты содержит только место в памяти, где хранятся данные. Вы не можете вывести из него какую-либо информацию о типе. Но вы можете передать в функцию два параметра: один для типа, а другой - для указателя.

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

6
ответ дан 18 December 2019 в 05:28
поделиться

Вы спрашиваете, как сделать интроспекцию в C. К сожалению, это не поддерживается.

Вместо этого вы можете использовать функции типа grep_char, как указал @anand.arumug. Или (если возможно) вы можете перейти на C++ и использовать его возможности перегрузки функций.

3
ответ дан 18 December 2019 в 05:28
поделиться

Прямой ответ: это невозможно. Кроме того, вам следует избегать написания таких суперфункций, которые действуют на несколько типов 2, если вы не можете по-настоящему обобщить код и применить полиморфизм. В C это часто связано с указателями на функции. В противном случае нет ничего плохого в написании нескольких функций, каждая из которых работает с одним типом. Фактически, это должно быть предпочтительнее суперфункций.

Вот базовый пример (не очень полезный, но простой):

#include <stdio.h>

typedef int less_function(void*, void*);

struct foo
{
    int data;
};

int foo_less(void* a, void* b)
{
    struct foo* f1 = a;
    struct foo* f2 = b;
    return f1->data < f2->data;
}

int find(void* search_array, void* element, int num, int element_size, less_function* less)
{
    int j = 0;
    char* search_pos = search_array;

    for (j=0; j < num; ++j, search_pos += element_size)
    {
        // if current element == element to find
        if (!less(search_pos, element) && !less(element, search_pos) )
            return j;
    }
    return -1;
}

int main()
{
    struct foo my_array[10] = { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {123}, {7}, {8} };
    struct foo search_element = {123};

    // outputs 7
    printf("%d\n", find(my_array, &search_element, 10, sizeof(struct foo), foo_less) );
}

В приведенном выше коде вы можете видеть, что у меня нет кода вроде: если этот тип является целым числом, сделайте это, если это число с плавающей запятой , сделайте это, если это объект struct foo, сделайте это и т. д. Вместо этого мы полагаемся на указатели функций, чтобы обеспечить настраиваемое поведение для сравнения типа передаваемого объекта.

qsort также делает это и является хороший пример для просмотра. Это очень похоже на функцию поиска выше, за исключением того, что ее компаратор не просто возвращает истину / ложь в зависимости от того, меньше ли первый объект, чем другой: он похож на strcmp и возвращает 0, -1 или +1.

3
ответ дан 18 December 2019 в 05:28
поделиться

Я думаю, вы обнаружите, что это невозможно в C.

В C++ есть шаблоны и перегрузка, которые являются хорошим решением для такого рода проблем.

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

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

2
ответ дан 18 December 2019 в 05:28
поделиться

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

2
ответ дан 18 December 2019 в 05:28
поделиться

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

Если вы должны передавать функции объекты без типов, то я предлагаю обернуть их в struct, который украсит их типом. Something like:

struct {
    enum TYPE { INT, CHAR, STRING } type;
    void *object;
}
1
ответ дан 18 December 2019 в 05:28
поделиться

Единственный способ, который я могу придумать, это либо передавать тип в качестве второго параметра, либо иметь структуру с указателем и перечислением или чем-то, определяющим тип, и передавать ее вместо простого указателя. В C нет встроенных метаданных, как в .net и Java, или даже эквивалента RTTI, о котором я знаю.

1
ответ дан 18 December 2019 в 05:28
поделиться

Как указывает Марк, это невозможно, но вы можете создавать перегруженные версии для ожидаемых типов.

Edit: Исправление, вы могли бы создать аналогичные функции для обработки различных типов:

void grep_c( char *t ) 
{ 
    do this 
}

void grep_i( int *t ) 
{ 
    do that  
}

В последнее время я слишком много писал на C ++!

-2
ответ дан 18 December 2019 в 05:28
поделиться

Если вы заранее знаете типы, с которыми будете работать, то можете определить функцию grep для каждого типа, например:

grep_int(int* pi);
grep_char(char* pc);
grep_float(float* pf);

Также определите макрос типа

#define GREP(T, TPTR_VAR) grep_##(TPTR_VAR)

Таким образом, вызов типа GREP(int, pi) будет переведен в grep_int(pi)

-1
ответ дан 18 December 2019 в 05:28
поделиться

Нет, это невозможно.

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

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

enum TYPE( TYPE_1, TYPE_2, TYPE_3,TYPE_MAX}; /*Add other data types into this enum if need be */

Назовите записи перечисления в соответствии с вашими требованиями.

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

1
ответ дан 18 December 2019 в 05:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: