C: экстраполяция типа из пустого указателя - PullRequest
11 голосов
/ 09 апреля 2010

Скажем, функция принимает в качестве аргумента пустой указатель, например: int func(void *p);
Как мы можем определить или угадать тип того, на что указывает p?

Ответы [ 4 ]

23 голосов
/ 09 апреля 2010

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

Данные и аргументы функций в C - это просто куча битов, объединенных вместе. Если вы не используете некоторые из этих битов, чтобы сказать вам, что это за биты, нет единого способа их идентифицировать.

6 голосов
/ 09 апреля 2010

Конечно, можно, и это тоже легко.Это C, делай что хочешь, как хочешь.

Создай систему типов.Поместите все, что вы передаете, в структуру, сделайте первый или два байта магическим числом, чтобы определить, что структура содержит за пределами магического числа.

Сделайте несколько функций для создания / получения / установки / уничтожения «типизированных переменных»,

Сделайте некоторые другие функции для добавления и регистрации новых типов во время выполнения.

Создайте несколько определений, чтобы упростить чтение и типизацию структур.

Прежде чем вы это узнаетеу вас будет хорошая проприетарная система типов, которую вы можете использовать для своих проектов, и она всегда будет делать именно то, что вы хотите и нуждаетесь, потому что вы сделали это.система.Или сохраните себе работу и используйте работу всех других людей, которые уже сошли с ума - http://en.wikipedia.org/wiki/GObject

6 голосов
/ 09 апреля 2010

Краткий ответ - вы не можете.

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

Система типов - ваш друг. Используйте это.

0 голосов
/ 23 мая 2013

Я столкнулся с подобной проблемой, и мне пришлось написать набор инструкций для проекта на языке программирования. Я столкнулся с этой проблемой, потому что у меня был массив указателей на функции, чтобы функции можно было перечислять и запускать в цикле for (для таких вещей, как онлайн-справка, синтаксис и т. Д.). Например:

struct List_Str  *(*InstructionSet[])(struct List_Str *ContextPrefix,struct List_Str *ContextSuffix)=
{

  AAVF,Add,AddEmotions,AddEmoDebug,AddScope,...

};

Теперь вы можете легко сделать то же самое с типами char * вместо типов struct List_Str *, а затем преобразовать все данные в строковый формат, используя snprintf и atoi, atof и другие функции преобразования. Если вы делаете:

man isalpha

Здесь показано множество функций в ctype.h, которые могут дать вам идеи, как определить, какой тип данных содержится в строках.

Сворачивание всех типов в «строковый» формат обеспечивает огромную гибкость и регулярность, но автоматическое преобразование данных из строк в целые числа, числа с плавающей запятой и т. Д. Является трудным, но плодотворным после того, как подпрограммы отформатированы.

Если вы намереваетесь хранить двоичные данные, то вы не можете использовать строки, так как 0 двоичных символов могут быть внутри двоичных данных, и это сбивает с толку функции strlen. Кроме того, вы не имеете представления о длине того, что было malloc'ом после того, как оно покидает область видимости, поэтому сохраняйте длину разыменованных данных до того, как данные будут рекомендованы в первых нескольких байтах char *.

И последнее: я бы не рекомендовал хранить данные в void *, это слишком расплывчато. Я рекомендую использовать char *, так как он немного конкретнее, может содержать все, что может void *, и компилятор сообщит вам заранее, если что-то будет выглядеть подозрительно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...