Char vs int调用约定

时间:2016-04-03 04:30:26

标签: c ocaml calling-convention

是否有任何32位或64位平台上int8_tint16_tint32_t的传递方式不同?

我问,因为OCaml(4.03 +,尚未发布)可以直接传递32位或64位整数和双精度到C,但不能传递8位或16位整数或单精度浮点数。 / p>

编辑:基本上我在询问是否

char x(char y)

可以称为

int x(int y)

3 个答案:

答案 0 :(得分:1)

调用约定中的关键字是约定,约定有很多原因,例如体系结构等。我可能正在使用int8_t但在幕后它可能占用32位空间或64位系统64位。只要它表现得像int8_t我就不在乎。语言可能会公开char但它可能表示为int,C表示这样做。当你在比C高得多的抽象层次的C语言接口中,你开始看到编译器编写者为简化生活而做出的一些设计决策。

答案 1 :(得分:1)

即使是,如果有32位或64位平台,int8_tint16_tint32_t以不同方式传递(我怀疑是,由于各种原因),这不是OCaml无法通过这些论点的借口。它所要做的只是遵循平台的标准ABI,世界将是正常的。很可能,FFI根本没有实现它,因为它对实施者来说不够有用。

话虽这么说,你不太可能找到这样一个平台的一个主要原因是因为大多数C编译器试图保留一些,至少是令牌,与K& RC兼容,在那里没有必要声明函数原型;未声明的函数将被调用,就好像它们有int个参数并返回值一样。由于这些原因,几乎所有ABI总是将所有整数参数提升为本机字大小,因此它们将与实际使用的任何具体整数类型进行赋值兼容,即使可以使用较小的更有效地传递参数单元。

编辑:要回答您编辑的问题,然后在所有有些标准的ABI上,是的,您可以将char x(char)称为int x(int)。但是,有一点需要注意的是,编译器可能会认为传递的字的高阶位为零,因此,如果您将512作为传递给char,则可能会获得未定义的行为。在C函数中用作{{1}}的参数。

答案 2 :(得分:1)

  

是否存在以不同方式传递int8_t,int16_t和int32_t的32位或64位平台?

据推测,存在一种,可能是实验的或历史的。但是,如果我们将话语领域限制为OCaml系统支持的一组架构(主要实现),那么答案就是否定。

  

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

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

OCaml的int32int64nativeintfloat都表示为盒装值,即它们在OCaml'中分配。 s堆并将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是错误代码,或者已知它是小的或不大于输入参数时。