Семантические различия в Алголе и С в кастинге

Предположим, у нас есть следующие инструкции в Алголе 68 и С, соответственно:ref int x := 5; а также (int*) x = 5;, В чем их семантическая разница?, это то же самое?, потому что я думаю, что второй говорит что-то вроде "х будет указывать на константу" (это не может быть скомпилировано), а первый говорит "х будет указывать на память ячейка, которая указывает на другую ячейку памяти, которая содержит константу 5". Это правильно? Если нет, можете ли вы объяснить это немного и привести несколько примеров, чтобы понять это?

2 ответа

Решение

Я не претендую на звание эксперта по Алголу-68 (или Алгол-60) - я никогда не собирал ничего на одном языке.

Тем не менее, Википедия о декларации режима Algol 68 гласит:

Тем не менее, декларация real x; это просто синтаксический сахар для ref real x = loc real;, То есть, x действительно постоянный идентификатор для ссылки на недавно сгенерированный локальный real переменная.

Учитывая это объяснение, фрагмент Алгола вопроса:

ref int x := 5;

соответствует (более или менее) коду C:

int *x = malloc(sizeof(*x));
*x = 5;

оставляя в стороне вопросы проверки ошибок и освобождения выделенной памяти.

Фрагмент вопроса C:

(int *)x = 5;

в значительной степени бессмысленно - результат приведения не является изменяемым lvalue, и вы можете назначить только изменяемое lvalue. Если переписано как:

int x_data;
int *x = &x_data;
*(int *)x = 5;

тогда это становится действительным C, хотя приведение полностью излишне. Конечно, можно было бы также использовать распределение памяти. В C любое использование x для доступа к целочисленному значению (в отличие от указателя) требуется разыменование в C (*x или же x[0]). В отличие от этого, в Алголе 68 нет необходимости явно разыменовывать переменную x,

Хотя вопрос упоминает "константу" пару раз, я не вижу ничего, что подразумевало бы постоянство в коде. Значение 5 присваивается переменной в местоположении. Значение, сохраненное в местоположении, может быть изменено позже другим назначением.

Заголовок вопроса спрашивает о приведении, но я не вижу доказательств приведения в коде Algol, и неясно, почему приведение считается необходимым в C-коде.

В Algol 68 доступно много неявных принуждений, зависящих от контекста (сильный, твердый, кроткий, слабый и мягкий контекст): см. Википедия и иерархия приведения Algol68.

Algol68 может неявно обрабатывать:

  1. увеличение точности и размеров (Сильный)
  2. объединяющий разные типы (фирма)
  3. целевая разыменование (как кроткая, так и слабая)
  4. процедура, депроцедура (Soft)

C casting имеет более ограниченное неявное приведение:

  1. ограничивается неявным "расширением" точности и float в int только в некоторых случаях. Расширение до массивов требует указателей и ручного кодирования с использованием оператора "&".
  2. Союзы должны быть закодированы / созданы вручную.
  3. Нет разыменования во время приведения (C вынуждает кодера явно определять, сколько раз разыменовывать указатель, используя оператор "*").
  4. Процедура без аргументов должна быть явно определена по имени и вызываться с использованием оператора "()".

Пример кода с выводом...

Файл: deref_and_cast.c

#include <stdio.h>
#include <stdlib.h>

main(){
  auto int*** crrri;
  crrri=(int***)malloc(sizeof(int**));
  *crrri=(int**)malloc(sizeof(int*));
  **crrri=(int*)malloc(sizeof(int));
  ***crrri=255; /* coder to explicitly work out how many times dereference */
  printf("%5.1f\n",(float)***crrri); /* Again deref is muilt-explicit */
}

Выход:

255.0

Файл: coerce_and_cast.a68

#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #

LOC REF REF REF INT crrri;
REF REF REF REF INT(crrri):=HEAP REF REF INT;
REF REF REF INT(crrri):=HEAP REF INT;
REF REF INT(crrri):=HEAP INT;
REF INT(crrri):=255; # targeted dereferencing (3x) depending on contect #
printf(($"example meek coercion:"g(-5,1)l$,REAL(crrri)));

Примеры Иерархии неявных принуждений

PROC VOID raise exception = end; # Implicitly cast a "GO TO" to a PROC #

# Soft: deprocedure a PROC to a VALUE #
printf(($"Soft:"gl$,random)); # Implicit Coercion #
printf(($"Soft:"gl$,REAL(random))); # Explicitly cast/deprocedure #

# Weak: dereference pointer chain to a "name" (LHS in C lingo) #
COMPL compl:= 0;
re OF compl := crrri; # Implicit Coercion #
REF REAL(re OF compl) := crrri; # Explicitly cast/dereference #
printf(($"Weak:"g(-0,4)g(7,4)"i"l$,compl));

# Meek: dereference to a value #
printf(($"Meek:"gl$,sin(crrri))); # Implicit Coercion #
printf(($"Meek:"gl$,sin(REAL(crrri)))); # Explicitly cast/dereference #

# Firm: unite to a UNION #
MODE IRC=UNION(INT,REAL,COMPL);
OP SIN = (IRC z)IRC: (z|(INT i):sin(i),(REAL r):sin(r),(COMPL z):complex sin(z));
printf(($"Firm:"gl$,SIN 1)); # Implicit Coercion #
printf(($"Firm:"gl$,SIN IRC(1))); # Explicitly cast/unite #

# Strong: widen to higher precision OR to an array #
FLEX [0]BOOL bool array := BIN crrri; # Implicit Coercion #
bool array := []BOOL(BIN crrri); # Explicitly cast/widen #
printf(($"Strong:"$,$g$,bool array,$l$));

end: SKIP

Выход:

example meek coercion:255.0
Soft:+2.11679610884246e  -1
Soft:+4.01945464342605e  -1
Weak:255.0000+0.0000i
Meek:-5.06391634924491e  -1
Meek:-5.06391634924491e  -1
Firm:+8.41470984807897e  -1
Firm:+8.41470984807897e  -1
Strong:FFFFFFFFFFFFFFFFFFFFFFFFTTTTTTTT

Алгол68 строго подходил к значению "имени" (что не то же самое, что "идентификатор"). Одним из видимых результатов этого является то, что Algol68 имеет тенденцию иметь еще один ref в типе / режиме объекта, чем в других языках.

таким образом INT является режимом постоянного целого числа (которому может даже не потребоваться выделение памяти во время выполнения). REF INT режим "целочисленной переменной", и REF REF INT является режимом "ссылки на целочисленную переменную".

 INT x = 42; 
 REF INT y = LOC INT := x; 
 REF REF INT z = LOC REF INT := y;

LOC - это "локальный генератор", который, по сути, просто выделяет пространство стека и возвращает его "имя" (он же адрес).

(Обратите внимание, что '=' устанавливает эквивалентность, а ':=' присваивает значение)

Желательный знакомый синтаксис означал, что в двух объявлениях переменных могут использоваться сокращенные формы:

INT y := x;
REF INT z := y;

но режим y все еще REF INTи т. д. ИМО, эта аббревиатура была плохой идеей.

С эквивалентность:

 #define x 42
 int y = x;
 int* z = &y;
Другие вопросы по тегам