2010-04-09 2 views

ответ

20

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

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

+6

Голосование ... вы знаете, потому что вы убедились в том, что в остальной части вашей программы. Если это звучит хрупко, это потому, что оно хрупкое. Добро пожаловать в C. Используйте менее хрупкую систему, в которой вы можете. –

+0

Я помню некоторый код Мотива (всего прочего), где бы вы не указали указатель, и вы бы посмотрели на первые байты после указателя, чтобы определить, что это за тип, и затем вы соответствуете этому типу. Какой беспорядок. – WhirlWind

+0

Я не буду делать это на практике. Мне было просто любопытно, как это можно сделать. Кроме того, расширение GNU C предоставляет оператор typeof(), который (я думаю) сможет определить тип разыменованных (т. Е. Typeof (* p)), но я еще не использовал его. – Yktula

5

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

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

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

5

Уверен, что вы можете, и это тоже легко. Это C, делайте все, что хотите, как хотите.

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

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

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

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

Прежде чем вы это узнаете, у вас будет хорошая система типов, которую вы можете использовать для своих проектов, и она всегда будет ТОЧНО, что вы хотите и нуждаетесь, потому что ВЫ ее сделали.

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

+0

Итак, как это работает, когда функция, которую вы пишете, вызывается из кода, который вы не контролируете? – WhirlWind

+2

Если функция вызывается из кода, который вы не контролируете, вы создаете API/библиотеку, поэтому вам нужно документировать интерфейс и функции для создания/получения/установки/уничтожения типизированных переменных. Если по какой-либо причине контролер является контролирующим, и они не хотят/отказываются использовать вашу пользовательскую «типизированную» систему, тогда вам не повезло. Вы должны позволить им решить, как они собираются передать вам введенную информацию и код. – Antebellum

1

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

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

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

}; 

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

man isalpha 

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

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

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

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

+2

Если вы используете 'char *' в качестве общего указателя данных, слишком легко ИМХО случайно разыменовать указатель без предварительного преобразования в соответствующий тип. –

Смежные вопросы