Концепция пустого указателя в C-программировании - PullRequest
123 голосов
/ 28 марта 2009

Можно ли разыменовать пустой указатель без приведения типов в языке программирования C?

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

например ::1005 *

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-адреса.

Также возможна ли арифметика указателей с пустыми указателями?

Ответы [ 15 ]

0 голосов
/ 04 марта 2019

Вот краткий указатель на void указателей: https://www.learncpp.com/cpp-tutorial/613-void-pointers/

6,13 - Пустые указатели

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

Если указатель void не знает, на что он указывает, как мы узнаем, к чему его привести? В конечном счете, это зависит от вас.

Справочник по пустым указателям

Невозможно выполнить арифметику указателя для пустого указателя. Это связано с тем, что арифметика указателей требует, чтобы указатель знал, на какой объект размера он указывает, поэтому он может соответствующим образом увеличивать или уменьшать указатель.

Предполагая, что память машины адресуется по байту и не требует выравниваемого доступа, наиболее общий и атомарный (самый близкий к представлению уровня машины) способ интерпретации void* - это указатель на байт, uint8_t*. Приведение void* к uint8_t* позволит вам, например, распечатать первые 1/2/4/8 / байт сколько угодно, начиная с этого адреса, но вы не можете сделать много остальное.

uint8_t* byte_p = (uint8_t*)p;
for (uint8_t* i = byte_p; i < byte_p + 8; i++) {
  printf("%x ",*i);
}
0 голосов
/ 03 мая 2018

void указатель является универсальным указателем. Адрес любого типа данных любой переменной может быть назначен пустому указателю.

int a = 10;
float b = 3.14;
void *ptr;
ptr = &a;
printf( "data is %d " , *((int *)ptr)); 
//(int *)ptr used for typecasting dereferencing as int
ptr = &b;
printf( "data is %f " , *((float *)ptr));
//(float *)ptr used for typecasting dereferencing as float
0 голосов
/ 27 июня 2017

Это не сработает, но void * может сильно помочь в определении общего указателя на функции и передаче его в качестве аргумента другой функции (аналогично обратному вызову в Java) или в определении структуры, аналогичной oop.

0 голосов
/ 25 марта 2017

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

0 голосов
/ 15 февраля 2013

Вы можете легко распечатать пустой принтер

int p=15;
void *q;
q=&p;
printf("%d",*((int*)q));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...