Тип печати void в чистом C - PullRequest
       38

Тип печати void в чистом C

8 голосов
/ 27 января 2009

у меня есть такая функция, как

void printMe (void *i)
{
    printf("%d", i);
}

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

Ответы [ 4 ]

24 голосов
/ 27 января 2009

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

A: Не так, как вы хотите. Вам нужно будет передать информацию в функцию, указав тип передаваемых данных.

Q2: и если да, то как это возможно, потому что это полностью ускользает от меня в данный момент.

A: Это ускользает от вас, потому что это невозможно сделать. Нет метаданных, связанных с void *, которые компилятор или среда выполнения могут использовать для определения типа, на который он указывает. Вам нужно либо

  1. передать структуру, содержащую
    указатель и информация о том, что
    указатель указывает на (например, перечисление).
  2. передать дополнительный параметр с информация о том, что указатель указывает на

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

Пустой указатель указывает на необработанные данные, printf предполагает, что вы знаете, какой тип данных вы печатаете, у него нет интеллекта и он не может «выяснить это» для вас.

Это так просто.

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

Надеюсь, это поможет.

Также. , , " В C нет перегрузок, которые я обычно использую в C ++ "

Даже в c ++ перегрузка происходит во время компиляции, и здесь у компилятора нет возможности узнать, какие данные будут переданы этой функции, поэтому, даже если вы привыкли к перегрузке, она никогда не будет работать так (например, попробуйте то же самое, используя printf, но скомпилируйте его с помощью компилятора C ++, вы получите точно такие же результаты). На самом деле попробуйте

cout << i;

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

cout << *(int*)i;

Итак, чтобы вышеперечисленное работало в C ++, вам нужно иметь много перегруженных функций (или шаблонную функцию, что на самом деле одно и то же, за исключением того, что компилятор сворачивает эти функции для вас), например перегруженные функции

printMe(int i){...}
printMe(double d){...}
printMe(char c){...}
printMe(char* string){...}

В c вам просто нужно дать этим функциям определенные имена

printInt(int i){...}
printDouble(double d){...}
printChar(char c){...}
printString(char* string){...}
7 голосов
/ 27 января 2009

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

Если вы действительно хотите это сделать, одно из решений:

void printMe (void *p, int typ) {
    switch(typ) {
        case TYP_INT: printf("%d", *((int*)p)); break;
        case TYP_CHR: printf("%c", *((char*)p)); break;
        /* and so on ... */
    }
}
0 голосов
/ 27 января 2009

Если вы пытаетесь распечатать значение указателя, правильное использование - printf("%p", i);. Спецификатор 'd' для целых чисел, а 'p' для указателей. Вы несете ответственность за то, чтобы все было правильно, и если вы их перепутаете, могут случиться плохие вещи.

Я не знаю, почему это не сработает для char *, а не для int *, и, возможно, у вас есть другие проблемы, вызывающие это. Если это все еще не удается с% p, что-то еще испортилось. Посмотрите, можете ли вы установить какое-либо программное обеспечение для мониторинга памяти, чтобы проверять наличие висячих указателей или двойных free (), потому что в этот момент умные деньги означают, что вы где-то испортили память.

0 голосов
/ 27 января 2009

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

Да, мы можем. Такая функция уже является частью стандартной библиотеки - она ​​называется printf;)

Поскольку в C нет перегрузки функции времени компиляции, вам нужно каким-то образом указывать тип аргументов во время выполнения. Для этого можно использовать строку формата printf, поэтому на самом деле нет причин создавать собственную функцию-обертку, когда уже есть работающее решение.

...