比方说,我们创建了 C 的重新实现,唯一的区别是 类型是推断出来的。存储类和修饰符仍然需要 给定(const、static、restrict 等),让我们将注意力限制在单个 暂时归档 C 程序。能做到吗?主要有哪些 障碍?
关于可能导致类型推断问题的一些想法
强制转换可能需要“from”注释,例如
var i = (uint32_t -> uint64_t) *some_pointer;
这些问题需要一些用户注释,但不应该太多 繁重的,是否有一些致命的问题让这个想法从水中消失?
编辑:澄清一下,我不是在谈论添加泛型或多态性,只是对现有 C 类型进行类型推断。
编辑 2014:任何对这个概念感兴趣的人都可能想研究一下 Rust
GCC 5.1 支持:
__auto_type
扩展,类似 C++11 auto
typeof
扩展,类似于 C++11 decltype
/* Same as: double j = 0.5; */
typeof(1 + 0.5) j = 0.5;
assert(j == 0.5);
Linux 内核示例:Linux 内核中的类型检查宏如何工作?
_Generic
C11 关键字:C11 中 _Generic 的语法和示例用法
__auto_type i = 1;
assert(_Generic((i), int: 1, default: 0));
C 自动提升某些类型,这使事情变得复杂。 但为了可行,您需要与 C 存在一些额外的差异:目前,该标准仍然在某种程度上支持旧版 K&R C 程序,并且这要求以特定方式处理未指定的类型。 (例如,参见没有原型的函数参数规则。过去也可以用 no 类型指定函数和变量,并且它们将默认为
(int)
。(变量如何?存储仅类。static foo;
))在添加新的隐含类型机制之前,必须删除所有这些遗留类型处理。
要推断多态函数的类型需要对 C 类型系统进行大量扩展。 示例
length(p) {
if (p == NULL) return 0;
else return 1 + length(p->next);
}
此代码必须适用于任何指向具有
next
字段的结构(或联合)的指针。 您可以检查行多态性,但至少,您的新类型系统必须比 C 类型系统更具表现力。
另一个紧迫的问题是超载
+
运行。 默认是什么类型? 您是否希望它在任何数字类型上重载,例如 Haskell 或 C++? 如果是这样,请对类型系统进行更大的扩展。
更大的教训是不要这样做。 C 的优点(作为一种语言,除了 C 中提供的许多优秀 API 之外)是
这个议程与多态性并不真正兼容,而多态性是类型推断的主要好处。 如果您想要类型推断,请选择多种原生支持它的优秀语言(F#、Haskell、ML)之一。
C 有一套关于类型提升和转换的复杂规则,即使人们实际上可以看到他们正在处理的类型,也会感到困惑。我怀疑即使 C 有类型推断,也有必要声明类型以防止每隔三个函数出现可笑的错误。
可以在 C 中进行 some 类型推断。请查看此工具:http://cuda.dcc.ufmg.br/psyche-c。您可以在那里键入程序的一部分,它将重建丢失的类型声明。例如,如果我们向它提供诺曼程序的变体:
int length(T p) {
if (p == NULL) return 0;
else return 1 + length(p->next);
}
然后 psyche-c 找到这些声明:
#include <stdint.h>
#define NULL ((void*)0)
typedef int bool;
bool false = 0;
bool true = 1;
typedef struct T {struct T* next;}* T;
这种类型重构对于代码完成等很有用。
我认为无法使用推断类型的某些情况:
我认为它可以适用于几种情况,主要是简单的局部变量。
即使像计算校验和这样简单的事情也需要一个明确的类型
crc8 = 0x00; /* 8 bits; cf uint8_t crc8 = 0; */
crc32 = 0x00000000; /* 32 bits; cf uint32_t crc32 = 0; */
可以做到,但用途有限。