Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

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

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

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

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

Что вы можете сделать, так это передать информацию о типе функции, но тогда вы получите что-то очень похожее на printf it's self, где вы передаете строку форматирования, содержащую информацию о типе данных в следующих аргументах.

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

Также ..."В 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){...}

Другие советы

Для начала вы печатаете указатель, а не то, на что он указывает.Чтобы распечатать фактическое содержимое, вам необходимо передать *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 ... */
    }
}

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top