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?
Semantic differences in Algol and C in casting
404 views Asked by Tomás Juárez AtThere are 3 answers
On
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;
On
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
floattointin 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
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:
Given that explanation, the question's Algol fragment:
corresponds (more or less) to the C code:
putting aside issues of error checking and release of the allocated memory.
The question's C fragment:
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:
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
xto access an integer value (as opposed to a pointer) requires dereferencing in C (*xorx[0]). By contrast, in Algol 68, there's no need to explicitly dereference the variablex.Although the question mentions 'constant' a couple of times, I see nothing that implies constancy in the code. The value
5is 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.