Подтвердить что ты не робот

Почему у нас есть указатели, отличные от void

Я знаю, что у нас есть разные указатели, такие как int, float и char. Указатель void - единственный указатель, который может содержать все остальные.

Существуют ли другие указатели только для гибкости для арифметики указателей?

Есть ли другая причина, по которой указатели, отличные от void, присутствуют на языке C?

4b9b3361

Ответ 1

Введите безопасность. Определение типа указателей помогает компилятору найти ошибки, когда вы пытаетесь использовать данные неправильного типа с помощью указателя. То, что причина C имеет типы в первую очередь.

Ответ 2

Компилятор должен знать типы, указав, что в противном случае все виды кода не будут работать. Рассмотрим следующее:

*a = *b + *c;    // Should this add char? int? float?
s_ptr->x = 0;    // How does the compiler know anything about the structure s_ptr points to?
a[5] = 0;        // How far is a[5] from a[0]?

Не имея типов для указателей, они бы не имели типов для чего-либо. Компилятор будет полностью потерян. Короче говоря, C и С++ строго типизированы, и это переносится на указатели по довольно очевидным причинам.

Ответ 3

int o = 12;
void *i = &o;

Как вы получите доступ к int, который указывает i, если были только указатели void и нет int *. Возможно, вы знаете, что на вашей платформе int составляет 4 байта, поэтому вы можете memcpy 4 байта от начала того, что void * указывает на временный int, а затем использовать это. Но это не очень удобно.

Или задан

struct Pair {
   char *first;
   char *second;
};

Насколько полезен указатель void на struct Pair? Вероятно, вы захотите получить доступ к своему члену first и много работать, если у вас не было указателя на структурную пару.

Ответ 4

Мертвый просто:

void* p;
*p; // compile error!

Или выразить словами; указатель void не может быть разыменован.

Возможно, вам следует переименовать вопрос, почему у нас есть указатели, или, скорее, нет, и просто искать этот вопрос на SO.

Ответ 5

Когда вы используете указатель на float или int (например), компилятор знает, сколько байтов оно должно взять из памяти (sizeof (int) для int * например).

С void Вам нужно было бы каждый раз рассказать о том, сколько байтов оно должно принять (например, путем записи (int *) some_void_ptr.

Но это большое упрощение.

Ответ 6

Собственно, это объясняется "указатель на пустоту".

В языках программирования вообще и в C, в частности, нам нравятся типы. Типы - это базовая система безопасности, которая проверяет, делаем ли мы что-то глупое, где "глупо" означает "интерпретировать кучу бит для чего-то, чего нет". Можно программировать без типов, некоторые языки полностью лишены какого-либо типа (например, сборка или Forth), но это не для слабонервных, и, вообще говоря, производительность программиста значительно улучшается за счет использования типов.

Поэтому, когда у нас есть указатель, мы хотим, чтобы компьютер знал, что он может найти в конце указателя. Нам нужен "указатель на int", чтобы компьютер проверял, что, когда мы смотрим на биты, которые находятся в конце указателя, мы рассматриваем их как "int", а не как что-то еще.

"Указатель на void" - это указатель без указания типа, который мы используем, когда система типов C не может захватить то, что мы делаем. Это признак того, что C не может выполнить сложность кода, который мы производим (или, может быть, программист недостаточно хорош, чтобы выразить то, что он делает в рамках ограничений системы типа C). Следовательно, в то время как "void *" удобно в некоторых ситуациях, следует рассматривать его как исключение и стремиться избегать его.

Ответ 7

Тип указателя в C указывает компилятору, какой размер блока памяти следует читать, если вы попытаетесь разыменовать его. Другими словами, при разыменовании указателя int компилятор знает, что после адреса нужно прочитать 4 байта. Вот почему разыменование указателя void без его указания на типизированный указатель запрещается - в этом случае компилятор не знает, сколько байтов следует читать после адреса.

Ответ 9

Когда вы повторяете блок памяти, на который указывает указатель, необходимо знать размер типа данных, который содержит память. Скажем, у вас есть два указателя: charcharptr и intintptr, указывающие на память в байте X. charptr + 1 укажет на байт X + 1, а intptr + 1 укажет на байт X + 4.

Быстрый и грязный кусок плохо написанного кода, чтобы проиллюстрировать это:

#include <stdio.h>

int main()
{
    char * cptr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    short * sptr = (short*)cptr;
    int * iptr = (int*)cptr;
    long long * lptr = (long long*)cptr;

    printf ("CHAR: %d, +1: %d\n",cptr,cptr+1);
    printf ("SHORT: %d, +1: %d\n",sptr,sptr+1);
    printf ("INT: %d, +1: %d\n",iptr,iptr+1);
    printf ("LONG LONG: %d, +1: %d\n",lptr,lptr+1);
}

Это должно:

  • генерировать предупреждения о указателях разливки разных размеров (тип безопасности),
  • выводятся идентичные числа в первом столбце (все указатели указывают на один и тот же адрес в памяти), но разные числа во втором столбце (который является базовым адресом + размером типа указателя: 1, 2, 4 и 8 байтов).

Ответ 10

Есть ли другая причина, по которой указатели, отличные от void, присутствуют на языке C?

Они - отличный способ свободно обрабатывать куски памяти.:)