在C中隐含函数声明实际上生成对象代码? [英] Do Implict Function Declarations in C Actually Generate Object Code?

查看:229
本文介绍了在C中隐含函数声明实际上生成对象代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在本次讨论过程中,关于投放返回值 malloc 许多人声称 malloc 的隐式声明会导致返回值被转换到 int ,然后重新转换回 T * ,可能会导致截断指针:

In the course of this discussion about casting the return value of malloc many people have claimed that the implicit declaration of malloc would cause the return value to be converted to int then reconverted back to T* possibly resulting in truncation of the pointer in situations where:

sizeof(int) < sizeof(void*)

这意味着编译器执行以下操作:

This would imply that the compiler does the following:


  1. 链接到并调用定义 malloc
  2. 的正确对象代码
  3. 生成用于将返回值转换为较短int类型的对象代码

  4. 生成目标代码以转换回更大的目标指针类型

有人真的可以证明这种情况吗?在64位Linux上用一些示例代码说:

Could someone actually prove that this happens? Say with some example code on 64bit Linux?

我自己做,但我没有访问64位机器。

I'd do it myself, but I don't have access to a 64 bit machine.

推荐答案

您的描述的问题是在第2步。使用隐式声明,调用站点的代码不会转换返回值的函数,真的。

The problem with your description of what happens is in step 2. With an implicit declaration, the code at the calling site doesn't "convert" the return value of the function, really.

会发生什么情况,调用站点的代码通过提取返回值(通常来自寄存器或堆栈)它的类型是int。对不同的操作系统和编译器执行此操作的过程是不同的,通常由ABI文档指定。

What happens is that the code at the calling site extracts the return value (typically from a register, or off the stack) by assuming that it's of type "int". The procedure to do this is different for different OSes and compilers, and is typically specified by an ABI document.

对于最常见的ABI,int和void *的返回位置和大小是相同的,所以你实际上不会有任何问题,即使它不正确。这在Linux,Windows和Mac OS X上,在32位和64位平台上都是如此,我相信 32位平台。

For the most common ABIs, the return location and sizes of int and void* are the same, so you actually won't have any problem doing this, even though it's incorrect. This is true for Linux, Windows, and Mac OS X on both 32- and 64-bit platforms, I believe 32-bit platforms.

在64位平台上,long和void *的大小是相同的,所以如果你有一个malloc ,返回值将被截断。不过,有几种流行的64位编程模型。

On 64-bit platforms, it's more common for "long" and "void *" to be the same size, so if you have an implicit declaration for malloc(), the return value will be truncated. There are several popular 64-bit programming models, though.

回到DOS开发的古老的日子,可以创建以int为16位,指针为32位的模式运行的程序实际上,24)。在这些情况下,使用隐式原型调用malloc()将截断返回的值。

Back in the "good old days" of DOS development, it was possible to create programs that ran in a mode where "int" was 16 bits, and pointers were 32 bits (actually, 24). In those cases, calling malloc() with an implicit prototype would truncate the returned value.

请注意,即使在返回值被截断的情况下,有一个运行时问题,取决于该值是否实际上在int的有效范围之外。

Note that even in the cases where the return value is truncated, you still might not have a runtime problem, depending on the whether the value is actually outside the valid range of an int.

X,在64位模式下,此代码:

On Mac OS X, in 64-bit mode, this code:

#include <stdio.h>

int main (int argc, const char * argv[]) {
    int x = malloc(128);
    void *p = malloc(128);
    printf("Hello, World!\nsizeof(int)=%d,sizeof(void*)=%d,x=0x%xd,p=%p\n", sizeof(int), sizeof(void *), x, p);
    return 0;
}

列印:

Hello,World!
sizeof(int)= 4,sizeof(void *)= 8,x = 0x1001c0d,p = 0x100100240

Hello, World! sizeof(int)=4,sizeof(void*)=8,x=0x1001c0d,p=0x100100240

x值具有比p值更少的数字,已经静默地丢弃该值的最高有效32位。在两个调用malloc的实际汇编代码如下所示:

Note that the "x" value has fewer digits than the "p" value, having silently dropped the most-significant 32 bits of the value. The actual assembly code at the two calls to malloc looks like this:

LM2:
    movl    $128, %edi
    call    _malloc
    movl    %eax, -12(%rbp)
LM3:
    movl    $128, %edi
    call    _malloc
    movq    %rax, -8(%rbp)

因此,正确的值由malloc(%rax)返回, movl指令在它被移动到变量x时截断它。

So, the right value is being returned by malloc (in %rax), but the movl instruction truncates it as it's being moved into variable "x".

这篇关于在C中隐含函数声明实际上生成对象代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆