“cdecl”是什么意思?代表?

发布于 2024-10-17 05:54:15 字数 282 浏览 11 评论 0原文

是的,我知道“cdecl”是一个著名的调用约定的名称,所以请不要向我解释调用约定。我要问的是缩写(?)“cdecl”实际上代表什么。我认为这是一个糟糕的命名选择,因为乍一看它让人想起“C​​ 声明符”(C 的一个相当独特的语法方面)。事实上,有一个名为 cdecl 的程序,其唯一目的是破译 C 声明符。但据我所知,C 声明符语法与调用约定完全无关。

简化版本:“stdcall”代表“标准调用约定”。 “cdecl”代表什么?

Yes, I know that "cdecl" is the name of a prominent calling convention, so please don't explain calling conventions to me. What I'm asking is what the abbreviation (?) "cdecl" actually stands for. I think it's a poor naming choice, because at first sight it reminds one of "C declarator" (a rather unique syntactic aspect of C). In fact, there is a program called cdecl whose sole purpose is to decipher C declarators. But the C declarator syntax has absolutely nothing to do with calling conventions as far as I can tell.

Simplified version: "stdcall" stands for "standard calling convention". What does "cdecl" stand for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

难得心□动 2024-10-24 05:54:15

它来自已声明的 C 函数(与 K&RC 中常见的未声明的 C 函数相反)。

当时它与 pascal 调用约定(被调用者清除堆栈)共存,因此在编程语言之后调用它是有意义的。

您可能想了解的有关调用约定的所有内容。

It comes from C function that was declared (in contrast to a C function that was not declared which was common in K&R C).

At the time it was coexisting with pascal calling convention (wher the callee cleared the stack), so it kind of made sense to call it after the programming language.

Everything you might ever want to know about calling conventions.

画中仙 2024-10-24 05:54:15

你读得太多了。它代表一般调用 C 函数的实现的调用约定(但对于可变参数尤其重要)。

它不一定是“C”和“声明”组合的缩写;名字只是名字,尤其是在编程中。助记符很有帮助,但尽管“malloc”的意思是“分配内存”,但它还有我们知道并附加的附加含义;例如,“alloca”也“分配内存”。

或者采用“struct”,它“意味着”“结构”,但“结构”本身是如此通用,如果没有我们潜意识中赋予“结构”的含义,我们将无可救药地迷失——因为仍在学习术语的新程序员经常会迷失。

You're reading too much into this. It stands for the calling convention of the implementation for calling C functions in general (but especially important with varargs).

It doesn't have to be an abbreviation for something that combines "C" and "declaration"; names are just names, especially in programming. Mnemonics help, but even though "malloc" means "allocate memory", it has additional meaning that we know and attach to it; "alloca" also "allocates memory", for example.

Or take "struct" which "means" a "structure", but "structure" is so generic by itself that without the meaning we attach subconsciously to "struct" we would be hopelessly lost – as new programmers still learning the terminology are often lost.

时间你老了 2024-10-24 05:54:15

C 声明。由/为 C 引入的声明。

[编辑]

老实说,我必须承认我实际上不知道这是否代表什么,尽管它实际上是由/为 C 引入的。但是由于调用者 必须清理分配的内存(与大多数其他调用约定相反)。它也可能是“来电者结束清洁”的助记符,我认为这实际上是一个很好的记忆帮助。 :D

C declaration. A declaration introduced by/for C.

[edit]

I honestly have to admit I don't actually know if that is what is stands for, although it is actually introduced by/for C. But since the caller has to clean up allocated memory (as opposed to most other calling conventions). It could also be a mnemonic for 'Caller Does End CLeaning' which I think is actually a good memory aid. :D

幻想少年梦 2024-10-24 05:54:15

CDECL 一词源自 Microsoft 的 BASIC 及其混合语言编程生态系统。该生态系统允许 Microsoft 四种主要语言(BASIC、FORTRAN、Pascal 和 C)中的任何一种语言调用任何其他语言。每种语言的调用约定都略有不同,并且每种语言都有一种方法来声明使用特定约定的外部函数或过程。

在 BASIC 中,必须先使用 DECLARE 语句,然后才能使用 CALL 语句调用外部函数。要表示外部 FORTRAN 或 Pascal 过程或函数,您将编写一种与

DECLARE SUB Foo ()
DECLARE FUNCTION Foo ()

其他语言不同的 C 调用约定,部分原因是参数以相反的顺序压入堆栈。您可以通过添加 CDECL 修饰符来通知 BASIC:

DECLARE SUB Foo CDECL ()
DECLARE FUNCTION Foo CDECL ()

相反,当用 FORTRAN 或 Pascal 编写时,修饰符是 [C]。这表明 CDECL 特定于 BASIC 的 DECLARE 语句,而不是
先前确定的术语。当时,还没有“C 调用约定”的具体术语。只有随着 WIN32 中新的调用约定(stdcall、fastcall 等)的出现,“cdecl”才被增选并成为在没有其他术语的情况下引用旧约定的事实上的名称。

综上所述,CDECL的意思是“C声明”。它起源于 BASIC 编译器,而不是 C 编译器,并且它是任意选择的 BASIC 关键字,并且有些多余,因为普通的“C”不能是关键字。

有关 CDECL 的详细信息可以在 1987 年的文档中找到:

https: //archive.org/details/Microsoft_Macro_Assembler_5.1_Mixed_Language_Programming_Guide/page/n1/mode/2up?q=cdecl

The term CDECL originates from Microsoft's BASIC and their Mixed Language Programming ecosystem. The ecosystem permitted any of the Microsoft's four major languages (BASIC, FORTRAN, Pascal and C) to make calls to any other. Each language had a slightly different calling convention, and each had a way to declare an external function or procedure to be using a specific convention.

In BASIC, the DECLARE statement had to be used before you could call an external function with the CALL statement. To denote an external FORTRAN or Pascal procedure or function, you would write one of

DECLARE SUB Foo ()
DECLARE FUNCTION Foo ()

C calling conventions differed from the other languages in part because the arguments were pushed on the stack in reverse order. You would inform BASIC of this by adding the CDECL modifier:

DECLARE SUB Foo CDECL ()
DECLARE FUNCTION Foo CDECL ()

By contrast, when writing in FORTRAN or Pascal, the modifier is [C]. This is an indication CDECL was specific to BASIC's DECLARE statement and not
a previously established term. At the time, there was no specific term for "C calling conventions". Only with the advent of new calling conventions in WIN32 (stdcall, fastcall, etc) did "cdecl" get co-opted and become the de-facto name to refer to the legacy conventions in the absence of another term.

In summary, CDECL means "C declaration". It had its origins in BASIC compilers, not C compilers, and it was an arbitrarily-chosen BASIC keyword, and somewhat redundant because plain "C" could not be a keyword.

Details about CDECL can be found in this 1987 document:

https://archive.org/details/Microsoft_Macro_Assembler_5.1_Mixed_Language_Programming_Guide/page/n1/mode/2up?q=cdecl

暮光沉寂 2024-10-24 05:54:15

cdecl(C 声明)调用约定通常是 x86 C 编译器的默认调用约定

在计算机科学中,调用约定是一种实现级(低级)方案,用于说明子例程如何从调用者接收参数以及如何返回结果。各种实现的差异包括参数、返回值、返回地址和作用域链接的放置位置(寄存器、堆栈或内存等),以及如何在调用者和调用者之间划分准备函数调用和随后恢复环境的任务。被调用者。

(来源)

调用约定可能与特定编程语言的评估策略,但大多数情况下不被视为其一部分(反之亦然),因为评估策略通常是在更高的抽象级别上定义的,并被视为语言的一部分,而不是特定的低级实现细节语言的编译器。

(来源)

cdecl(代表 C 声明)是一种调用约定,源自 Microsoft 的 C 编程语言编译器,并被许多 x86 架构的 C 编译器使用。在cdecl中,子例程参数在堆栈上传递。整数值和内存地址在 EAX 寄存器中返回,浮点值在 ST0 x87 寄存器中返回。寄存器EAXECXEDX 由调用者保存,其余寄存器由被调用者保存。调用新函数时,x87 浮点寄存器 ST0ST7 必须为空(弹出或释放),并且 ST1ST7退出函数时 必须为空。当不用于返回值时,ST0 也必须为空。

在 C 编程语言的上下文中,函数参数按从右到左的顺序压入堆栈,即最后一个参数首先压入。

考虑以下 C 源代码片段:

int callee(int, int, int);

int caller(void)
{
    return callee(1, 2, 3) + 5;
}

在 x86 上,它可能会生成以下汇编代码(Intel 语法):

caller:
    ; make new call frame
    ; (some compilers may produce an 'enter' instruction instead)
    push    ebp       ; save old call frame
    mov     ebp, esp  ; initialize new call frame
    ; push call arguments, in reverse
    ; (some compilers may subtract the required space from the stack pointer,
    ; then write each argument directly, see below.
    ; The 'enter' instruction can also do something similar)
    ; sub esp, 12      : 'enter' instruction could do this for us
    ; mov [ebp-4], 3   : or mov [esp+8], 3
    ; mov [ebp-8], 2   : or mov [esp+4], 2
    ; mov [ebp-12], 1  : or mov [esp], 1
    push    3
    push    2
    push    1
    call    callee    ; call subroutine 'callee'
    add     esp, 12   ; remove call arguments from frame
    add     eax, 5    ; modify subroutine result
                      ; (eax is the return value of our callee,
                      ; so we don't have to move it into a local variable)
    ; restore old call frame
    ; (some compilers may produce a 'leave' instruction instead)
    mov     esp, ebp  ; most calling conventions dictate ebp be callee-saved,
                      ; i.e. it's preserved after calling the callee.
                      ; it therefore still points to the start of our stack frame.
                      ; we do need to make sure
                      ; callee doesn't modify (or restores) ebp, though,
                      ; so we need to make sure
                      ; it uses a calling convention which does this
    pop     ebp       ; restore old call frame
    ret               ; return

调用者在函数调用返回后清理堆栈。

cdecl 调用约定通常是 x86 C 编译器的默认调用约定,尽管许多编译器提供了自动更改所使用的调用约定的选项。要手动将函数定义为 cdecl,有些支持以下语法:

return_type __cdecl func_name();

调用约定是调用约定的名称。 __cdecl__stdcall__pascal
可以在支持的编译器的 C++ 函数声明中显式指定 __fastcall
这些约定。 __cdecl 是应用程序和静态库的默认值。 __stdcall
系统调用(包括 Windows API 调用)的默认值和库的推荐值
32 位 Windows 中的 DLL。 Microsoft 编译器默认使用 __thiscall 作为成员
16 位和 32 位模式下的功能。 Microsoft、Borland、Watcom 和 Gnu 是以下品牌
编译器。适用于 Windows 的英特尔编译器与 Microsoft 兼容。英特尔编译器
Linux 与 Gnu 兼容。 Symantec、Digital Mars 和 Codeplay 编译器
与微软兼容。在 64 位模式下,每一个都有一个默认的调用约定
操作系统,而其他调用约定在 64 位模式下很少见。

其他约定:

  • __pascal
  • __fortran
  • __thiscall
  • __stdcall
  • __fastcall
  • __msfastcall
  • __regcall
  • __vectorcall

(来源)< /em>

The cdecl (C Declaration) calling convention is usually the default calling convention for x86 C compilers

In computer science, a calling convention is an implementation-level (low-level) scheme for how subroutines receive parameters from their caller and how they return a result. Differences in various implementations include where parameters, return values, return addresses and scope links are placed (registers, stack or memory etc.), and how the tasks of preparing for a function call and restoring the environment afterwards are divided between the caller and the callee.

(Source)

Calling conventions may be related to a particular programming language's evaluation strategy, but most often are not considered part of it (or vice versa), as the evaluation strategy is usually defined on a higher abstraction level and seen as a part of the language rather than as a low-level implementation detail of a particular language's compiler.

(Source)

The cdecl (which stands for C declaration) is a calling convention that originates from Microsoft's compiler for the C programming language and is used by many C compilers for the x86 architecture. In cdecl, subroutine arguments are passed on the stack. Integer values and memory addresses are returned in the EAX register, floating point values in the ST0 x87 register. Registers EAX, ECX, and EDX are caller-saved, and the rest are callee-saved. The x87 floating point registers ST0 to ST7 must be empty (popped or freed) when calling a new function, and ST1 to ST7 must be empty on exiting a function. ST0 must also be empty when not used for returning a value.

In the context of the C programming language, function arguments are pushed on the stack in the right-to-left order, i.e. the last argument is pushed first.

Consider the following C source code snippet:

int callee(int, int, int);

int caller(void)
{
    return callee(1, 2, 3) + 5;
}

On x86, it might produce the following assembly code (Intel syntax):

caller:
    ; make new call frame
    ; (some compilers may produce an 'enter' instruction instead)
    push    ebp       ; save old call frame
    mov     ebp, esp  ; initialize new call frame
    ; push call arguments, in reverse
    ; (some compilers may subtract the required space from the stack pointer,
    ; then write each argument directly, see below.
    ; The 'enter' instruction can also do something similar)
    ; sub esp, 12      : 'enter' instruction could do this for us
    ; mov [ebp-4], 3   : or mov [esp+8], 3
    ; mov [ebp-8], 2   : or mov [esp+4], 2
    ; mov [ebp-12], 1  : or mov [esp], 1
    push    3
    push    2
    push    1
    call    callee    ; call subroutine 'callee'
    add     esp, 12   ; remove call arguments from frame
    add     eax, 5    ; modify subroutine result
                      ; (eax is the return value of our callee,
                      ; so we don't have to move it into a local variable)
    ; restore old call frame
    ; (some compilers may produce a 'leave' instruction instead)
    mov     esp, ebp  ; most calling conventions dictate ebp be callee-saved,
                      ; i.e. it's preserved after calling the callee.
                      ; it therefore still points to the start of our stack frame.
                      ; we do need to make sure
                      ; callee doesn't modify (or restores) ebp, though,
                      ; so we need to make sure
                      ; it uses a calling convention which does this
    pop     ebp       ; restore old call frame
    ret               ; return

The caller cleans the stack after the function call returns.

The cdecl calling convention is usually the default calling convention for x86 C compilers, although many compilers provide options to automatically change the calling conventions used. To manually define a function to be cdecl, some support the following syntax:

return_type __cdecl func_name();

Calling convention is the name of the calling convention. __cdecl, __stdcall, __pascal and
__fastcall can be specified explicitly in C++ function declarations for compilers that support
these conventions. __cdecl is the default for applications and static libraries. __stdcall is
the default for system calls (including Windows API calls) and recommended for library
DLL's in 32-bit Windows. __thiscall is used by default in Microsoft compilers for member
functions in 16 and 32 bit mode. Microsoft, Borland, Watcom and Gnu are brands of
compilers. Intel compilers for Windows are compatible with Microsoft. Intel compilers for
Linux are compatible with Gnu. Symantec, Digital Mars and Codeplay compilers are
compatible with Microsoft. In 64 bit mode, there is one default calling convention for each
operating system, while other calling conventions are rare in 64 bit mode.

Other Conventions:

  • __pascal
  • __fortran
  • __thiscall
  • __stdcall
  • __fastcall
  • __msfastcall
  • __regcall
  • __vectorcall

(Source)

谎言月老 2024-10-24 05:54:15

C 有函数和变量的概念,汇编程序/机器代码没有。当想要将值传递给函数时,需要使用 cpu 寄存器或内存中距离寄存器(通常是指定的堆栈指针)固定偏移量的值来完成。因此,当我们在函数开头跳转到新地址时,正确的值位于正确的位置,以便函数正确执行。这同样适用于返回值。

它在实践中如何工作在描述系统调用约定的文档中定义。调用约定对于 CPU 架构和操作系统来说都是独特的。

在 x86 Windows 上,使用了许多调用约定。在“cdecl”调用约定中,调用者将函数放在堆栈上供被调用者使用。一旦函数完成,调用者就会清理自己的堆栈。

Windows API 使用“stdcall”调用约定,该约定与 cdelc 类似,只是被调用者清理堆栈。 (这意味着无法使用vararg函数调用call)。它的优点是节省代码空间。

Windows 还有一个“fastcall”调用约定,它利用寄存器进行参数传递。

由于 Windows 允许多种调用约定,C 编译器 (cl) 通过 __cdecl__stdcall__fastcall 扩展了 C 语言。这装饰了函数声明并允许程序员指定所使用的调用约定。

其他平台(如 ARM、Itanium 等)有自己的调用约定。

C has the concept of functions and variables, assembler / machine-code do not. When one wants to pass values to functions, this needs to be done either using cpu registers, or a value in memory at a fixed offset from a register (normally the designated stack pointer). Thus when we jump to a new address at the start of our function, the right values are in the right places so that the function performs correctly. Same applies for return values.

How this works in practice is defined in a document that describes to system's calling conventions. The calling convention is something unique to both the CPU architecture and the operating system.

On x86 Windows there are a number of calling conventions that are used. In the "cdecl" calling convention the caller places functions on the stack for the callee to use. Once the function completes, the caller cleans up its own stack.

Windows APIs use the "stdcall" calling convention which is similar the cdelc except that the callee cleans up the stack. (This means vararg function calls call cannot be used). It has the benefit of saving code space.

Windows also has a "fastcall" calling convention that makes use of registers for parameter passing.

Since windows allows multiple calling conventions, C compiler (cl) extends the C language with __cdecl, __stdcall and __fastcall. This decorates the function declaration and allows the programmer to specify the calling convention used.

Other platforms like ARM, Itanium and others have their own calling conventions.

孤独患者 2024-10-24 05:54:15

CDECL没有缩写,它只是调用约定的名称。

如果这不是您要寻找的内容,那么实际上是 CDECL 的历史:

它是 Microsoft 特定的调用约定属性(在 1985 年到 1995 年之间引入),后来成为标准。

可惜页面从互联网上丢失了(回溯也什么也没有),但是谁有旧的 MSDN CD 可能会在“C 语言参考”中找到主题“声明摘要”,其中明确指出以下内容:

attribute-seq : /* attribute-seq 是 Microsoft 特定的 */

属性属性序列选项
属性:/* Microsoft 特定 */ 之一

__asm __fastcall
__基于__内联
__cdecl __stdcall

也在相同的旧 MSDN 文档 __cdecl 中

__cdecl 主页 |概述 |我该怎么办

Microsoft 特定 —>

这是 C 和 C++ 程序的默认调用约定。因为
堆栈由调用者清理,它可以执行可变参数函数。这
__cdecl 调用约定创建比 __stdcall 更大的可执行文件,因为它要求每个函数调用都包含堆栈清理代码。
下面的列表显示了这个调用的实现
约定。

否则,我们都会迷失在你的问题中(请修改它);)

CDECL has no abbreviation, it's just name for calling convention.

If that was not what you were looking for, but actually the history of CDECL then:

It's a Microsoft specific calling convention attribute (at the time of introduction somewhere between 1985 and 1995), that later became the standard.

Too bad page is lost from Internet (wayback also has nothing), but who has old MSDN CD's might find topic "Summary of Declaration" inside "C Language Reference" that clearly states following:

attribute-seq : /* attribute-seq is Microsoft Specific */

attribute attribute-seq opt
attribute : one of /* Microsoft Specific */

__asm __fastcall
__based __inline
__cdecl __stdcall

also in same old MSDN documenttion __cdecl

__cdecl Home | Overview | How Do I

Microsoft Specific —>

This is the default calling convention for C and C++ programs. Because
the stack is cleaned up by the caller, it can do vararg functions. The
__cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code.
The following list shows the implementation of this calling
convention.

otherwise, we all are lost in your question (please revise it) ;)

∞琼窗梦回ˉ 2024-10-24 05:54:15

更新 在评论指出我的错误有多么严重之后,我已经完全修改了这一点。 cdecl 表示该函数使用与 C 函数相同的调用约定。此外,extern "C" 还意味着函数名称不应进行 C++ 名称修改。

至于为什么叫cdecl,我就不太清楚了。

Updated I've totally revised this, after the comments pointing out how wrong I was. cdecl means that this function uses the same calling convention that C functions use. extern "C" means, in addition, that the function name should not undergo C++ name-mangling.

As for why it's called cdecl, I don't know any more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文