首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在C中内嵌函数声明是否实际生成对象代码?

在C中内嵌函数声明是否实际生成对象代码?
EN

Stack Overflow用户
提问于 2009-10-14 13:05:28
回答 3查看 307关注 0票数 1

在讨论malloc的过程中,许多人声称malloc的隐式声明会导致返回值被转换为int,然后再转换回T*,可能会导致指针在以下情况下被截断:

代码语言:javascript
代码运行次数:0
运行
复制
sizeof(int) < sizeof(void*)

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

  1. 链接并调用定义malloc的正确目标代码
  2. 生成对象代码,以将返回值转换为较短的int类型。
  3. 生成对象代码,以将其转换回更大的目标指针类型。

真的有人能证明这事发生了吗?比如在64位Linux上使用一些示例代码?

我会自己做的,但我没有64位机器的权限。

EN

回答 3

Stack Overflow用户

发布于 2009-10-14 13:20:02

Malloc是在stdlib.h文件头中声明的,声明由源代码的C预处理器直接包含,然后在以后的阶段与malloc代码链接。

当您有代码时:

代码语言:javascript
代码运行次数:0
运行
复制
#include <stdlib.h>
...
void * foo = malloc(42);

它实际上被加工成类似于

代码语言:javascript
代码运行次数:0
运行
复制
...
extern void *malloc (size_t __size) __attribute__ ((__nothrow__)) __attribute__ ((__malloc__)) ;
(...lots of other declarations...)
...
void * foo = malloc(42);

当您不包括函数原型时,它默认为

代码语言:javascript
代码运行次数:0
运行
复制
int malloc();
...
void * foo = malloc(42);

这意味着最终编译的代码将执行类似的操作,“使用参数42调用malloc,将其返回值从int转换为void*,并将其转换为foo”。然后,它将与带有malloc预编译对象代码的libc链接,这显然是无效的*-返回。因此,结果将是在保存返回值的CPU寄存器上进行一次额外的int*转换。我设想在64位架构上,它可能意味着接受较低的32位,并在前面放置32个零,从而清除部分原始指针。

票数 1
EN

Stack Overflow用户

发布于 2009-10-14 13:28:31

我认为2并不像你所暗示的那样是一种“宝贵”的转换。当使用返回类型未知的函数进行数据处理时,编译器必须对要“获取”的字节数做出一些假设。默认值是int的大小。

所以,如果一个空*和一个int恰好是相同的大小,那么,好的,如果不是oops!

票数 1
EN

Stack Overflow用户

发布于 2009-10-14 14:01:05

通过省略malloc的声明(prototype),编译器假定它返回int。因此,对它的调用作为代码生成,以调用返回int结果的函数。

根据系统的不同,这样做的方式不同,因此结果可能会在数据寄存器、地址寄存器或堆栈中被传回。

然后,编译器生成额外的代码,以将(推定的)返回的int值转换为指针。

很明显,这不是你想要的。在大多数系统上,您可能会很幸运,因为在这些系统中,ints和指针的宽度是相同的,因此返回值的转换基本上没有任何作用,但是不能依赖这种行为。

总之,--不声明外部函数是一件坏事。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1566107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档