gpt4 book ai didi

c - 将 float 传递给带有 int 参数的函数(未事先声明)

转载 作者:行者123 更新时间:2023-11-30 21:15:17 24 4
gpt4 key购买 nike

我已阅读Garbage value when passed float values to the function accepting integer parameters答案。我的问题有点深入。我还可以问问那里我的声望点是否超过了50点。我添加我的代码以获得更多说明:

#include <stdio.h>
#include <string.h>

void p2(unsigned int tmp)
{
printf("From p2: \n");
printf("tmp = %d ,In hex tmp = %x\n", tmp, tmp);
}

int main()
{
float fvar = 45.65;

p1(fvar);
p2(fvar);
printf("From main:\n");
printf("sizeof(int) = %lu, sizeof(float) = %lu\n", sizeof(int),
sizeof(float));
unsigned int ui;
memcpy(&ui, &fvar, sizeof(fvar));
printf("fvar = %x\n", ui);
return 0;
}

void p1(unsigned int tmp)
{
printf("From p1: \n");
printf("tmp = %d ,In hex tmp = %x\n", tmp, tmp);
}

输出为:

From p1: 
tmp = 1 ,In hex tmp = 1
From p2:
tmp = 45 ,In hex tmp = 2d
From main:
sizeof(int) = 4, sizeof(float) = 4
fvar = 4236999a8

float 值传递给预先使用 int 参数声明的函数(即 p2)会给出正确的结果。当尝试对未事先声明的函数(即 p1)执行相同操作时,会给出错误的值。我知道编译器不会为未事先声明的函数假设任何类型或参数数量的原因。这就是为什么在 p2 的情况下 float 值不会被类型转换为 int

我的困惑是,在 p2 的情况下,float 值到底如何复制到本地 int 变量 tmp。

如果它是“逐位复制”,那么读取这些位置应该至少产生十六进制的内容(除了 1)(如果不是整数)。但从输出结果来看,情况并非如此。我知道 float 表示是不同的。

p2 如何读取 float 未复制到的寄存器/堆栈位置?正如 simonc 在链接问题中建议的那样?

我已经包含了 intfloat 的大小,如果有帮助的话,我的编译器是 gcc。

最佳答案

C 编程语言本质上是一种单扫描语言 - 编译器不需要重新读取代码,但它可以逐行汇编代码,仅保留有关如何声明标识符的信息。

C89 标准有隐式声明的概念。如果没有声明,函数p1 被隐式声明为int p1();即返回 int 并接受通过默认参数提升的未指定参数的函数。当您调用此类函数并将 float 作为参数时,float 参数将提升为 double,正如默认参数提升所要求的那样。如果函数是 int p1(double arg) 就可以了;但预期的参数类型是 unsigned int,并且返回值也不兼容(voidint)。这种不匹配将导致程序出现未定义的行为 - 推理当时发生的事情是没有意义的。然而,如果编译器不支持过时的隐式声明,许多旧的 C 程序将无法编译 - 因此您只需将所有这些警告视为错误。

请注意,如果将 p1返回值更改为 int,您将收到更少的警告:

% gcc implicit.c
implicit.c:14:5: warning: implicit declaration of function ‘p1’ [-Wimplicit-function-declaration]
p1(fvar);
^~

但是在我的编译器上观察到的行为大部分是相同的。

因此,在新编写的代码中,仅仅出现警告:函数“x”的隐式声明很可能是一个严重错误

如果函数在使用之前声明(如 p2 的情况),则编译器知道它需要一个 unsigned long 作为参数,并返回 void,因此它会知道为参数生成从 floatunsigned long 的正确转换代码。

<小时/>

C99 和 C11 不允许在严格一致的程序中使用隐式函数声明 - 但它们也不需要一致的编译器来拒绝它们。 C11 说:

An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).

以及脚注指出

Thus, an undeclared identifier is a violation of the syntax.

但是,它不需要编译器来拒绝它们。

关于c - 将 float 传递给带有 int 参数的函数(未事先声明),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42549605/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com