Suppose we have the following instructions in Algol 68 and C, respectively:
ref int x := 5;
and (int*) x = 5;
. What are their semantic difference?, it's the same?, because I think that the second one says something like "x will point to a constant" (it can't be compiled) and the first one says "x will point to a memory cell that points to another memory cell that contains a constant, 5". Is it correct?, if not, can you explain it a bit and give some examples to understand this?

- 5,753
- 72
- 57
- 129

- 1,517
- 3
- 21
- 51
-
1The C is simply not valid. With the right setup, `*(int *)x = 5;` would be legal C, though perhaps a little dubious. – Jonathan Leffler Feb 02 '17 at 04:09
-
C for *x will point to this constant, and can be reassigned to point to another variable, but not used to modify the variable it points to,* is `static const int a = 5; const int* x = &a;`. C for, *x itself is not modifiable; it points only to this modifiable location in memory and cannot point to anything else,* is `int a = 5; int* const x = &a`, or, if you want to do it on a single line, `int x[1] = {5};` – Davislor Apr 03 '17 at 05:25
3 Answers
Algol 68 has many implicit coercions available depending on context (Strong, Firm, Meek, Weak & Soft Context): cf Wikipedia & Algol68's Coercion Hierarchy.
Algol68 can implicitly handle:
- widening of precision and dimension (Strong)
- uniting different types (Firm)
- targeted dereferencing (Both Meek and Weak)
- proceduring, deproceduring (Soft)
C casting has more restricted implicit casting:
- limited to implicit of 'widening' of precision and
float
toint
in some cases only. Widening to arrays requires pointers and manual coding using the "&" operator. - Unions must be manually coded/created.
- There is no dereferencing during casting (C forces the coder to explicitly work out how many times dereference a pointer using the "*" operator).
- procedure without arguments must be explicitly defined by name and called using the "()" operator.
Example code with output...
File: 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 */
}
Output:
255.0
File: 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)));
Examples of Hierarchy of implicit coercions
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
Output:
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

- 730,956
- 141
- 904
- 1,278

- 1,269
- 12
- 31
I don't pretend to be an Algol 68 (or Algol 60) expert — I've never compiled a thing in either language.
However, Wikipedia on Algol 68 mode declarations says:
However, the declaration
real x;
is just syntactic sugar forref real x = loc real;
. That is,x
is really the constant identifier for a reference to a newly generated localreal
variable.
Given that explanation, the question's Algol fragment:
ref int x := 5;
corresponds (more or less) to the C code:
int *x = malloc(sizeof(*x));
*x = 5;
putting aside issues of error checking and release of the allocated memory.
The question's C fragment:
(int *)x = 5;
is largely meaningless — the result of a cast is not a modifiable lvalue, and you can only assign to a modifiable lvalue. If rewritten as:
int x_data;
int *x = &x_data;
*(int *)x = 5;
then it becomes valid C, though the cast is wholly superfluous. It could also be written to use memory allocation, of course. In C, any use of x
to access an integer value (as opposed to a pointer) requires dereferencing in C (*x
or x[0]
). By contrast, in Algol 68, there's no need to explicitly dereference the variable x
.
Although the question mentions 'constant' a couple of times, I see nothing that implies constancy in the code. The value 5
is assigned to a variable in a location. The value stored in the location can be changed later by another assignment.
The question title asks about casting, but I see no evidence of a cast in the Algol code, and it is not clear why a cast is considered necessary in the C code.

- 730,956
- 141
- 904
- 1,278
-
Even if `(int *)x = 5;` could plausibly assign the address of `5` to the pointer `x` it would be well within system protected memory and any use or dereference would guarantee bad things would happen... – David C. Rankin Apr 03 '17 at 04:24
-
The answer is incorrect. Algol 68's **ref int** x:= 5; is precisely identical to C's **int** x = 5; it declares a sinple integer variable. Algol 68 is more pedantic over the meaning of names than more recent languages. An item that is an **int** is an integer value; an integer variable cannot 'be' an integer, it can only refer to (i.e., hold) an integer. – user13784117 Jul 12 '20 at 23:52
Algol68 took a rigorous approach to the meaning of a 'name' (which is not the same thing as an 'identifier'). One visible result of that is that Algol68 tends to have one-more-ref in the type/mode of an object than do other languages.
Thus INT
is the mode of a constant integer (which may not even need memory allocated at run time). REF INT
is the mode of an "integer variable", and REF REF INT
is the mode of a "reference to an integer variable".
INT x = 42;
REF INT y = LOC INT := x;
REF REF INT z = LOC REF INT := y;
LOC is a 'local generator' that essentially just allocates stack space and returns its 'name' (aka address).
(Note that '=' establishes an equivalence, and ':=' is assigning a value)
A desired for familiar syntax meant that the two variable declarations can use abbreviated forms:
INT y := x;
REF INT z := y;
but the mode of y
is still REF INT
, etc. IMO, that abbreviation was a bad idea.
C equivalence:
#define x 42
int y = x;
int* z = &y;