假设我们创建了C的重新实现,唯一的区别在于 推断出这些类型。存储类和修饰符仍然需要 给定(const,static,restrict等),让我们把注意力限制在单身 文件C程序暂时。可以吗?有什么专业 障碍?
关于什么可能导致类型推断出现问题的一些想法
强制转换可能需要一个“from”注释,类似于
var i = (uint32_t -> uint64_t) *some_pointer;
这些问题需要一些用户注释,但不应该这样 繁琐,是否有一些将这个想法从水中吹出的杀手问题?
编辑:为了澄清,我不是在谈论添加泛型或参数多态,只是对现有C类型进行类型推断。
编辑2014:任何对此概念感兴趣的人都可能需要查看Rust
答案 0 :(得分:10)
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内核示例:How does the typecheck macro from the Linux kernel work?
_Generic
C11关键字:Syntax and Sample Usage of _Generic in C11
__auto_type i = 1;
assert(_Generic((i), int: 1, default: 0));
答案 1 :(得分:6)
C会自动提升某些类型,这会使事情复杂化。但是为了可行,你需要与C存在一些额外的差异:现在,标准仍然在某种程度上支持传统的K& R C程序,并且要求以特定方式处理未指定的类型。 (例如,在没有原型的情况下,参见函数参数的规则。过去也可以使用 no 类型指定函数和变量,它们将默认为(int)
。(如何使用变量?仅限存储类。static foo;
))在添加新的隐含类型机制之前,必须删除所有这些遗留类型处理。
答案 2 :(得分:4)
要推断多态函数的类型,需要对C类型系统进行大幅扩展。实施例
length(p) {
if (p == NULL) return 0;
else return 1 + length(p->next);
}
此代码必须处理指向具有next
字段的结构(或联合)的任何指针。您可以检查行多态,但至少,您的新类型系统必须比C类型系统更具表现力。
另一个迫切的问题是重载+
操作。它默认是什么类型的?你想让它在任何数字类型上重载,比如Haskell或C ++吗?如果是这样,那么类型系统会有更大的扩展。
更大的教训是不要这样做。 C(作为一种语言,除了C中提供的许多优秀API之外)的优点是
这个议程与多态性并不真正兼容,而多态性是类型推断的主要好处。如果您想要类型推断,请选择支持它的许多优秀语言之一(F#,Haskell,ML)。
答案 3 :(得分:1)
可以在C中进行一些类型推断。看一下这个工具:http://cuda.dcc.ufmg.br/psyche-c。您可以在那里键入程序的一部分,它将重建缺少的类型声明。例如,如果我们用Norman程序的变体喂它:
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;
例如,这种类型的重建对于代码完成很有用。
答案 4 :(得分:0)
C有一套关于类型提升和转换的复杂规则,即使人们真正看到他们正在处理的类型,他们也会感到困惑。我怀疑即使C有类型推断,也有必要声明类型以防止每三个函数出现荒谬的错误。
答案 5 :(得分:0)
我认为无法使用推断类型的某些情况:
我认为它可能适用于少数情况,主要是简单的局部变量。
即使像计算校验和这样简单的事情也需要明确的类型
crc8 = 0x00; /* 8 bits; cf uint8_t crc8 = 0; */
crc32 = 0x00000000; /* 32 bits; cf uint32_t crc32 = 0; */
可以这样做,但用途有限。