![]() |
1
15
额外的参数不会被丢弃。它们被正确地放置在堆栈上,就好像调用了一个需要三个参数的函数一样。但是,由于您的函数只关心一个参数,所以它只查看堆栈的顶部,不接触其他参数。 事实上,这一呼吁起作用是纯粹的运气,基于以下两个事实:
编译器不可能出于一个简单的原因就这样的潜在问题向您发出警告——在一般情况下,它在编译时不知道指针的值,因此它无法评估它指向的内容。假设函数指针指向在运行时创建的类虚拟表中的一个方法?所以,你告诉编译器它是一个指向一个有三个参数的函数的指针,编译器会相信你的。 |
![]() |
2
12
如果你把一辆车当作锤子来铸成锤子,编译器会告诉你这辆车是一把锤子,但这并不能把它变成锤子。编译器可能会成功地使用汽车来驱动钉子,但这取决于实现的好运。这仍然是一件不明智的事情。 |
![]() |
3
3
|
![]() |
4
3
强制转换的最大错误是将数据指针强制转换为函数指针。它比签名更改更糟糕,因为无法保证函数指针和数据指针的大小相等。和很多相反 理论的 不确定的行为,这一个可以在野外遇到,甚至在先进的机器上(不仅在嵌入式系统上)。 在嵌入式平台上,您可能很容易遇到不同大小的指针。甚至有些处理器的数据指针和函数指针都能处理不同的事情(一个是RAM,另一个是ROM),这就是所谓的哈佛架构。在实模式下的x86上,可以混合16位和32位。watcom-c有一个特殊的DOS扩展模式,数据指针宽48位。尤其是对于C,人们应该知道并不是所有的东西都是POSIX,因为C可能是异域硬件上唯一可用的语言。 有些编译器允许混合内存模型,其中代码保证在32位大小内,数据可以通过64位指针或相反的指针寻址。 编辑: 结论:不要将数据指针强制转换为函数指针。 |
![]() |
5
2
行为由调用约定定义。如果使用调用方推送和弹出堆栈的调用约定,那么在这种情况下,它会很好地工作,因为它只意味着调用期间堆栈上有额外的几个字节。我现在没有GCC,但是有了Microsoft编译器,下面的代码:
为调用生成以下程序集:
注意调用后添加到堆栈的12个字节(0ch)。在此之后,堆栈就可以了(假设在本例中被调用方是uu cdecl,因此它不会尝试同时清理堆栈)。但使用以下代码:
这个
|
![]() |
6
1
|
![]() |
7
1
我应该在某个时候刷新对C调用约定的二进制布局的记忆,但我确信这就是发生的事情:
|
![]() |
8
0
要回答您的问题:
希望这有帮助, 最好的问候, 汤姆。 |
![]() |
MaPo · Linux,设置锁定ICMP_过滤器选项 4 月前 |
![]() |
Doohyeon Won · 内联函数上的奇怪现象?[关闭] 5 月前 |
![]() |
Bobby · 复合字面值总是左值吗? 5 月前 |
![]() |
9-Pin · C: 嵌套结构的堆栈内存分配 5 月前 |