2016-04-03 72 views
0

是否有任何32位或64位平台上的int8_t,int16_tint32_t以不同的方式传递?Char vs int调用约定

我在问,因为OCaml(4.03+,尚未发布)可以传递32或64位整数,并且可以直接加倍到C,但不是8位或16位整数或单精度浮点数。

编辑:基本上我问

char x(char y)

可以被称为

int x(int y)

+1

我无法想象任何架构上的任何调用约定都会允许在任何现代系统中使用该约定。对于基于寄存器的调用约定,每个参数都放在一个寄存器中。我不希望任何编译器尝试分配寄存器的一部分,这是全部或没有。无论如何,这可能会非常低效。对于基于堆栈的版本,您通常以字大小的块来推送参数,否则会导致错位。而且,效率很低。 –

+1

@JeffMercado:并不是说它与这个问题有关,但是当传递某些结构时,编译器确实将“寄存器的部分”分配给结构字段。例如,一个'struct {int a,b;}'将在AMD64上的一个reigster中传递,其中一半寄存器用于每个字段。 – Dolda2000

回答

1

在调用约定的关键词是公约和惯例不同的原因有很多,即架构等。我可能会使用int8_t,但在后台可能会占用32位或64位系统64位。只要它的行为像int8_t我不在乎。一种语言可能会暴露一个char,但它可能被表示为一个int,C做到这一点。当你深入到比抽象层次更高的语言C语言界面时,你会看到一些编译器编写者为了简化他们的生活而做出的一些设计决定。

1

即使如果有32位或64位平台,通过int8_t S,int16_t S和int32_t不同的方式过(我怀疑有,由于种种原因),那会不会是对的OCaml不找借口能够传递这样的论点。所有它需要做的就是遵循平台的标准ABI,世界就会好起来。很有可能,FFI根本就没有实现它,因为它对实施者来说不够有用。这就是说,为什么你不可能找到这样一个平台的一个主要原因是因为大多数C编译器试图保留一些,至少是令牌的兼容性,在那里它不需要声明函数原型;未声明的函数将被调用,就好像它们具有参数和返回值int一样。由于这样的原因,几乎所有的ABI都会将所有整数参数提升为本地字大小,因此它们将与实际使用的任何具体整数类型分配兼容,即使可以更有效地使用较小的参数单位。

编辑:要回答你的问题,编辑,然后对所有的标准有所ABI的,是的,你可以调用char x(char)作为int x(int)。然而,一个警告可能是,编译器可能会假定传递的字的高位为零,但是,如果您将(例如)512作为使用的参数传递,可能会导致未定义的行为作为C函数中的char

1

是否有任何32位或64位平台的int8_t,int16_t和int32_t传递不同?

推测存在一个,也许是实验性的或历史性的。但是,如果我们将话语范围限制在OCaml系统支持的一组体系结构(主要实现)中,那么答案是否定的。

我问,因为OCaml中(4.03+,还未被释放)可以 通32位或64位的整数和双打到C直接,但不是8个或 16位整数或单精密浮动。

原因是因为OCaml具有不同的整数表示形式。与C表示相比,它向左移一位并递增。因此0表示为C的1,13等等。最低有效位用于区分立即值和指针。所以OCaml整数有效地少了一位,即64位系统上的63位和32位系统上的31位。这一切都意味着,在将一个整数传递给c函数之前,您需要将其移到右侧。一个简单和低成本的操作。 char类型也由int代表,所以它具有相同的问题。标准库中没有int8_tint16_t,所以我不能谈论它们。第三方库可能会以任何形式介绍它们,可能支持也可能不支持直接传递给C函数。

OCaml中的int32int64nativeintfloat,都表示为装箱值,即它们OCaml中的堆被分配并围绕OCaml的功能通过用作指针。分配的块的表示与C中的相同,因此允许按原样传递它。当然,只有被调用的函数没有将这个值存储在某个地方,并且不会调用任何可能引发垃圾回收的函数,这才是安全的。在4.03之前,程序员需要通过将内容复制到C变量(安全方式),或者直接解引用并传递它(一种危险的方式 - 你应该知道你在做什么)来解开值。 4.03版本提供了新的注释(属性unboxed),这是对以前存在的"%float"注释的概括。这个注解允许直接传递这四种类型的值。此注释适用于有限的一组函数类型,当然,仅对特定函数是安全的。

因此,总而言之,小整数以非常快的速度传递给C.盒装值通常需要一些额外的工作,这也引入了对垃圾收集和分配的调用。为了减轻这一点,4.03增加了一些优化,如果它是安全的,可以直接传递它们。

编辑:基本上我问

char x(char y)

可以被称为

int x(int y)

但从OCaml的外部函数接口点没有大区别。唯一的问题是,OCaml int比C int小,因此如果x可能返回一个值,但不适合OCaml表示,应该使用更大(和盒装)类型,例如nativeint。在很多情况下,这个问题可以忽略,例如,当int是错误代码,或者已知它很小或不大于输入参数。