Можно ли разыменовать указатель void без преобразования типов в языке программирования C?
Кроме того, есть ли способ обобщить функцию, которая может получать указатель и сохранять его в указателе void, и, используя этот указатель void, можем ли мы создать обобщенную функцию?
например:
void abc(void *a, int b)
{
if(b==1)
printf("%d",*(int*)a); // If integer pointer is received
else if(b==2)
printf("%c",*(char*)a); // If character pointer is received
else if(b==3)
printf("%f",*(float*)a); // If float pointer is received
}
Я хочу сделать эту функцию универсальной без использования операторов if-else - возможно ли это?
Кроме того, если в Интернете есть хорошие статьи, объясняющие концепцию пустого указателя, было бы полезно, если бы вы могли предоставить URL-адреса.
Кроме того, возможна ли арифметика указателей с указателями void?
источник
void *
указателей так же, какchar *
, но это не стандарт, и вы не должны на него полагаться.В C a
void *
можно преобразовать в указатель на объект другого типа без явного приведения:Однако это не помогает при написании вашей функции в более общем виде.
Вы не можете разыменовать a
void *
с преобразованием его в другой тип указателя, так как разыменование указателя приводит к получению значения указанного объекта. Голыйvoid
тип не является допустимым, поэтому разграничениеvoid *
невозможно.Арифметика указателя заключается в изменении значений указателя на количество, кратное
sizeof
указанным объектам. Опять же, посколькуvoid
это не истинный тип,sizeof(void)
не имеет значения, поэтому арифметика указателя недействительнаvoid *
. (Некоторые реализации позволяют это, используя эквивалентную арифметику указателя дляchar *
.)источник
void abc(void *a, int b)
. Но почему бы не использоватьvoid abc(int *a, int b)
, поскольку в вашей функции, которую вы в конечном итоге определитеint *test = a;
, она сохранит одну переменную, и я не вижу других преимуществ при определении другой переменной. Я вижу много кодов, написанных таким образом, с использованием вvoid *
качестве параметров и приведением переменных позже в функции. Но так как эта функция написана автором, он должен знать использование переменной, поэтому зачем использоватьvoid *
? СпасибоВы должны знать, что в C, в отличие от Java или C #, нет абсолютно никакой возможности успешно «угадать» тип объекта, на который
void*
указывает указатель.getClass()
Ничего подобного просто не существует, так как этой информации нигде нет. По этой причине тип «универсального», который вы ищете, всегда идет с явной метаинформацией, такой какint b
в вашем примере или строка формата вprintf
семействе функций.источник
Указатель void известен как универсальный указатель, который может ссылаться на переменные любого типа данных.
источник
Пока что я недооцениваю указатель void следующим образом.
Когда переменная-указатель объявляется с использованием ключевого слова void - она становится переменной-указателем общего назначения. Адрес любой переменной любого типа данных (char, int, float и т. Д.) Может быть назначен переменной-указателю типа void.
Поскольку указатель на другой тип данных может быть назначен указателю void, я использовал его в функции absolut_value (код, показанный ниже). Чтобы сделать общую функцию.
Я попытался написать простой код на C, который принимает в качестве аргумента целое число или число с плавающей запятой и пытается сделать его + ve, если он отрицательный. Я написал следующий код,
Но я получал ошибку, поэтому я понял, что мое понимание с указателем void неверно :(. Итак, теперь я перейду к сбору очков, почему это так.
Что мне нужно больше понять о недействительных указателях, так это то, что.
Нам нужно привести тип переменной указателя void, чтобы разыменовать ее. Это связано с тем, что указатель void не имеет связанного с ним типа данных. Компилятор не может знать (или догадываться?), На какой тип данных указывает указатель void. Таким образом, чтобы взять данные, на которые указывает указатель void, мы приводим его к правильному типу данных, хранящихся внутри местоположения указателей void.
Указатель void может быть действительно полезен, если программист не уверен в типе данных, вводимых конечным пользователем. В таком случае программист может использовать указатель void, чтобы указать на местоположение неизвестного типа данных. Программа может быть настроена таким образом, чтобы запрашивать у пользователя информацию о типе данных, и приведение типов может выполняться в соответствии с информацией, введенной пользователем. Ниже приведен фрагмент кода.
Еще один важный момент, о котором следует помнить о пустых указателях, заключается в том, что арифметические операции с указателями не могут выполняться в пустых указателях.
Итак, теперь я понял, в чем была моя ошибка. Я исправляю то же самое.
Ссылки :
http://www.antoarts.com/void-pointers-in-c/
http://www.circuitstoday.com/void-pointers-in-c .
Новый код показан ниже.
Спасибо,
источник
Нет, это невозможно. Какой тип должно иметь разыменованное значение?
источник
источник
printf
. В этом ответе есть хороший пример.int b
это перечислением, но внесение каких-либо последующих изменений в это перечисление нарушило бы эту функцию.Единственный простой способ, который я вижу, - это использовать перегрузку .., которая недоступна в языке программирования C AFAIK.
Рассматривали ли вы язык программирования C ++ для своей программы? Или есть какое-то ограничение, запрещающее его использование?
источник
Вот краткий указатель на
void
указатели: https://www.learncpp.com/cpp-tutorial/613-void-pointers/Предполагая , что память аппарата являешься байтами-адресации и не требует выровненных доступов, наиболее общий и атомный (ближе к представлению уровня машины) способом интерпретации
void*
является как указатель на-а-байты,uint8_t*
. Преобразование avoid*
в auint8_t*
позволит вам, например, распечатать первые 1/2/4/8 / сколько бы вы ни пожелали байтов, начиная с этого адреса, но вы больше ничего не можете сделать.источник
Вы можете легко распечатать пустой принтер
источник
void
размер такой жеint
?void
указателя, а печать поint
адресу памяти, который содержит указатель (который в данном случае будет значениемp
).Поскольку C - это статически типизированный язык со строгой типизацией, вы должны выбрать тип переменной перед компиляцией. Когда вы пытаетесь имитировать дженерики на C, вы снова попытаетесь переписать C ++, поэтому было бы лучше использовать C ++.
источник
Указатель void - это универсальный указатель. Адрес любого типа данных любой переменной может быть назначен указателю void.
источник
Вы не можете разыменовать указатель без указания его типа, потому что разные типы данных будут иметь разные размеры в памяти, то есть int - 4 байта, char - 1 байт.
источник
По сути, в C «типы» - это способ интерпретации байтов в памяти. Например, что следующий код
Говорит: «Когда я запускаю main, я хочу выделить 4 (размер целого числа) + 4 (размер целого числа) = 8 (всего байтов) памяти. Когда я пишу '.x' как lvalue для значения с меткой типа Укажите во время компиляции, извлеките данные из области памяти указателя плюс четыре байта. Присвойте возвращаемому значению метку времени компиляции "int".
Внутри компьютера во время выполнения ваша структура «Point» выглядит так:
И вот как
void*
может выглядеть ваш тип данных: (на 32-битном компьютере)источник
Это не сработает, но void * может очень помочь в определении универсального указателя на функции и передаче его в качестве аргумента другой функции (аналогично обратному вызову в Java) или определение его структуры, аналогичной oop.
источник