TL; DR
Вполне возможно иметь язык без указателей.На самом деле, можно написать программу на C, в которой вы храните адреса в обычных целочисленных переменных, а затем приводите их к указателям.Вызывая указатели, а также общую концепцию типов, синтаксический сахар - это немного растянуть его, но это тоже не совсем верно.
Длинная история
Причина в том, что он очень ценен дляесть разные типы.Это позволяет компилятору выполнять проверку типов и автоматические преобразования.Это также позволяет компилятору предупреждать вас, когда вы делаете что-то, что, вероятно, не соответствует вашим намерениям.Например, посмотрите на этот код C:
int x;
int *p;
// Init x and p somehow
int y = p + x; // Legal, but you probably meant y = *p + x
Ранний язык B, который предшествовал C, имел только один тип, называемый "слово".Он использовался для целых чисел, указателей, чисел с плавающей точкой или чего-либо еще.Программа должна была интерпретировать битовую комбинацию.
Рассмотрим этот код C:
int i=5;
float f=3.5;
float x=f+i;
В последнем выражении i
будет преобразован в float
перед плавающей точкой.сложение выполняется.Это было бы невозможно без информации о типе.Теперь x
будет иметь значение 8.5
(ошибки округления игнорируются), но теперь рассмотрим этот псевдокод, иллюстрирующий проблему, с которой вы столкнетесь в языке типа B:
word i, f, x;
i = 5;
f = 3.5;
x = i + f;
Что вы ожидаете от переменной x
содержать?И какой тип должен представлять этот битовый шаблон?
Когда дело доходит до указателей, это очень ценно.Учтите, что у вас есть два указателя, char *cptr
и int *iptr
.Теперь давайте посмотрим на некоторую арифметику указателей.При добавлении целого числа к указателю мы сместим указатель относительно размера типа .Таким образом, *(cptr + 1)
вернет значение, которое составляет один байт после cptr
, тогда как *(iptr + 1)
(обычно) вернет значение, которое находится по адресу 4 или 8 байтов после iptr
.
Вот пример, очень близкий к вашему вопросу.Рассмотрим этот код C:
float *p = malloc(10 * sizeof (*p));
for(int i=0; i<10; i++)
p[i]= i * 1.2;
for(int i=0; i<10; i++)
printf("%f\n", p[i]);
Если бы у нас не было типов указателей, то мы должны были бы написать что-то вроде этого:
unsigned p = malloc(10 * sizeof(float));
for(int i=0; i<10; i++)
*(p + i*sizeof(float)) = i * 1.2;
for(int i=0; i<10; i++)
printf("%f\n", (float) *(p + i*sizeof(float)));
Если вы действительно хотите, вы можетена самом деле делать подобные вещи в C. Вот пример, который компилируется и запускается, хотя с предупреждениями и, возможно, имеет неопределенное поведение, но это дало ожидаемый результат на моем компьютере:
unsigned p = malloc(10 * sizeof(float));
for(int i=0; i<10; i++)
*((float*)p + i*sizeof(float)) = i * 1.2;
for(int i=0; i<10; i++)
printf("%f\n", *((float*)p + i*sizeof(float)));