Algol 和 C 在铸造中的语义差异
Semantic differences in Algol and C in casting
假设我们在Algol 68和C中分别有如下指令:
ref int x := 5;
和 (int*) x = 5;
。他们的语义区别是什么?,是一样的?,因为我认为第二个说的是"x will point to a constant"(无法编译),而第一个说的是"x will point to a memory cell that points to another memory cell that contains a constant, 5"。是否正确?如果不正确,您能否解释一下并举一些例子来理解这一点?
我不假装是 Algol 68 (or Algol 60) 专家 — 我从来没有用任何一种语言编译过任何东西。
然而,Algol 68 mode declarations 上的维基百科说:
However, the declaration real x;
is just syntactic sugar for ref real x = loc real;
. That is, x
is really the constant identifier for a reference to a newly generated local real
variable.
鉴于该解释,问题的 Algol 片段:
ref int x := 5;
对应(或多或少)C代码:
int *x = malloc(sizeof(*x));
*x = 5;
暂且不谈错误检查和释放已分配内存的问题。
问题的C片段:
(int *)x = 5;
在很大程度上是没有意义的——转换的结果不是一个可修改的左值,你只能分配给一个可修改的左值。如果改写为:
int x_data;
int *x = &x_data;
*(int *)x = 5;
然后它成为有效的 C,尽管转换完全是多余的。当然,它也可以写成使用内存分配。在 C 中,任何使用 x
来访问整数值(与指针相反)都需要在 C 中取消引用(*x
或 x[0]
)。相比之下,在 Algol 68 中,无需显式取消引用变量 x
.
尽管这个问题多次提到 'constant',但我没有看到任何暗示代码中的稳定性的内容。值 5
分配给某个位置的变量。存储在该位置的值以后可以通过另一个赋值来更改。
问题标题询问有关转换的问题,但我在 Algol 代码中没有看到转换的证据,并且不清楚为什么在 C 代码中认为转换是必要的。
Algol 68 有许多隐式强制转换可用,具体取决于上下文(强、稳、温、弱和软上下文):cf Wikipedia & Algol68's Coercion Hierarchy.
Algol68 可以隐式处理:
- 精度和尺寸的扩大(强)
- 团结不同类型(公司)
- 有针对性的取消引用(温顺和弱)
- 处理,去处理(软)
C 转换具有更严格的隐式转换限制:
- 仅在某些情况下限于 'widening' 精度和
float
至 int
的隐式。扩展到数组需要使用“&”运算符的指针和手动编码。
- 联合必须手动 coded/created。
- 转换过程中没有解引用(C 强制编码器明确计算出使用“*”解引用指针的次数
运算符)。
- 没有参数的过程必须通过名称明确定义并使用“()”运算符调用。
带有输出的示例代码...
文件: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
Algol68 对 'name' 的含义采取了严格的方法(这与 'identifier' 不同)。一个可见的结果是 Algol68 在对象的 type/mode 中往往比其他语言多一个引用。
因此INT
是常量整数的模式(甚至可能不需要在运行时分配内存)。 REF INT
是"integer variable"的模式,REF REF INT
是"reference to an integer variable"的模式。
INT x = 42;
REF INT y = LOC INT := x;
REF REF INT z = LOC REF INT := y;
LOC 是一个 'local generator',本质上只是分配堆栈 space 和 returns 它的 'name'(又名地址)。
(注意'='建立等价,':='是赋值)
熟悉的语法意味着两个变量声明可以使用缩写形式:
INT y := x;
REF INT z := y;
但是 y
的模式仍然是 REF INT
,等等。IMO,那个缩写是个坏主意。
C等值:
#define x 42
int y = x;
int* z = &y;
假设我们在Algol 68和C中分别有如下指令:
ref int x := 5;
和 (int*) x = 5;
。他们的语义区别是什么?,是一样的?,因为我认为第二个说的是"x will point to a constant"(无法编译),而第一个说的是"x will point to a memory cell that points to another memory cell that contains a constant, 5"。是否正确?如果不正确,您能否解释一下并举一些例子来理解这一点?
我不假装是 Algol 68 (or Algol 60) 专家 — 我从来没有用任何一种语言编译过任何东西。
然而,Algol 68 mode declarations 上的维基百科说:
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.
鉴于该解释,问题的 Algol 片段:
ref int x := 5;
对应(或多或少)C代码:
int *x = malloc(sizeof(*x));
*x = 5;
暂且不谈错误检查和释放已分配内存的问题。
问题的C片段:
(int *)x = 5;
在很大程度上是没有意义的——转换的结果不是一个可修改的左值,你只能分配给一个可修改的左值。如果改写为:
int x_data;
int *x = &x_data;
*(int *)x = 5;
然后它成为有效的 C,尽管转换完全是多余的。当然,它也可以写成使用内存分配。在 C 中,任何使用 x
来访问整数值(与指针相反)都需要在 C 中取消引用(*x
或 x[0]
)。相比之下,在 Algol 68 中,无需显式取消引用变量 x
.
尽管这个问题多次提到 'constant',但我没有看到任何暗示代码中的稳定性的内容。值 5
分配给某个位置的变量。存储在该位置的值以后可以通过另一个赋值来更改。
问题标题询问有关转换的问题,但我在 Algol 代码中没有看到转换的证据,并且不清楚为什么在 C 代码中认为转换是必要的。
Algol 68 有许多隐式强制转换可用,具体取决于上下文(强、稳、温、弱和软上下文):cf Wikipedia & Algol68's Coercion Hierarchy.
Algol68 可以隐式处理:
- 精度和尺寸的扩大(强)
- 团结不同类型(公司)
- 有针对性的取消引用(温顺和弱)
- 处理,去处理(软)
C 转换具有更严格的隐式转换限制:
- 仅在某些情况下限于 'widening' 精度和
float
至int
的隐式。扩展到数组需要使用“&”运算符的指针和手动编码。 - 联合必须手动 coded/created。
- 转换过程中没有解引用(C 强制编码器明确计算出使用“*”解引用指针的次数 运算符)。
- 没有参数的过程必须通过名称明确定义并使用“()”运算符调用。
带有输出的示例代码...
文件: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
Algol68 对 'name' 的含义采取了严格的方法(这与 'identifier' 不同)。一个可见的结果是 Algol68 在对象的 type/mode 中往往比其他语言多一个引用。
因此INT
是常量整数的模式(甚至可能不需要在运行时分配内存)。 REF INT
是"integer variable"的模式,REF REF INT
是"reference to an integer variable"的模式。
INT x = 42;
REF INT y = LOC INT := x;
REF REF INT z = LOC REF INT := y;
LOC 是一个 'local generator',本质上只是分配堆栈 space 和 returns 它的 'name'(又名地址)。
(注意'='建立等价,':='是赋值)
熟悉的语法意味着两个变量声明可以使用缩写形式:
INT y := x;
REF INT z := y;
但是 y
的模式仍然是 REF INT
,等等。IMO,那个缩写是个坏主意。
C等值:
#define x 42
int y = x;
int* z = &y;