问题
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?
回答1:
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.
回答2:
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
回答3:
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;
来源:https://stackoverflow.com/questions/41993990/semantic-differences-in-algol-and-c-in-casting