将float*转换为char*、int*和char*不会产生预期结果
据我所知,输出应该是3.14,3.14,3.14和256256,对吗?但这会产生不同的输出。有谁能告诉我为什么会这样将float*转换为char*、int*和char*不会产生预期结果,c,pointers,casting,C,Pointers,Casting,据我所知,输出应该是3.14,3.14,3.14和256256,对吗?但这会产生不同的输出。有谁能告诉我为什么会这样 main() { float a = 3.14; int b = 256; char *p, *p1; p = (char *) &a; p1 = (char *) &b; printf("\nFLOAT:"); printf("\nValue of *p=%f",*p);
main()
{
float a = 3.14;
int b = 256;
char *p, *p1;
p = (char *) &a;
p1 = (char *) &b;
printf("\nFLOAT:");
printf("\nValue of *p=%f",*p);
printf("\nValue of a=%f",a);
printf("\nValue of *p=%f",*p);
printf("\n\nINTEGER:");
printf("\nValue of *p1=%d",*p1);
printf("\nValue of b=%d",b);
printf("\nValue of *p1=%d",*p1);
}
Output:
FLOAT:
Value of *p=0.000000
Value of a=3.140000
Value of *p=3.140001
INTEGER:
Value of *p1=0
Value of b=256
Value of *p1=0
表达式
*p
的类型为char
。格式说明符%f
需要类型为float
的参数。将错误类型的参数传递给变量函数(如printf
)会调用未定义的行为。表达式*p
的类型为char
。格式说明符%f
需要类型为float
的参数。将错误类型的参数传递给变量函数(如printf
)会调用未定义的行为。由于float*和char*的大小不同,它的行为与预期不符。转换它们可能会牺牲您的表达准确性 由于float*和char*的大小不同,因此其行为与预期不符。转换它们可能会牺牲您的表达准确性 简单的回答是,当您使用%f
格式说明符将char
类型传递给printf
时,您正在调用未定义的行为,因此您不应该期望有任何特别的结果
很长的答案取决于实现,但接下来是我对您的平台上可能发生的情况的观察。当您要求printf
打印double
值时(与%f
格式说明符一样),它从堆栈中读取下一个sizeof(double)
字节,并将其解释为浮点值并打印。在第一次printf
调用中,第一次生成新的堆栈帧时,堆栈上实际传递的char
后的数据等于零浮点值。在对printf
的第二次调用中,生成了一个新的堆栈帧,可能覆盖了第一次调用所覆盖的相同空间。在这种情况下,会出现一个完整的double
值,并按预期进行打印。当函数返回时,堆栈帧被“销毁”。为了提高效率,当函数返回且内容保持不变时,堆栈帧通常不会归零。在第三次调用printf
时,再次传递一个字节,而要求printf
将sizeof(double)
字节解释为浮点值。上一次调用printf
的堆栈帧现在包含上一次调用传递的double
的值,其中一个字节被新参数的字节覆盖,从而打印出值
如果我将您的第二个printf
呼叫更改为:
printf("\nValue of a=%f", 1.234);
第三次调用printf
打印(在我的系统上):
这似乎验证了上述逻辑
总之,您要求
printf
从堆栈中读取的数据比实际传递给函数的数据多,因此,结果是未定义的。在您的情况下,读取的数据是以前调用的剩余数据,这解释了您在特定平台上得到的结果。(正如Ray指出的,参数的实际传递方式可能会有所不同,因为这取决于实现。有些系统会在寄存器中传递值,但点保持不变。)简而言之,当您使用%f
格式说明符将char
类型传递给printf
时,您正在调用未定义的行为,因此您不应该期望有任何特殊情况
很长的答案取决于实现,但接下来是我对您的平台上可能发生的情况的观察。当您要求printf
打印double
值时(与%f
格式说明符一样),它从堆栈中读取下一个sizeof(double)
字节,并将其解释为浮点值并打印。在第一次printf
调用中,第一次生成新的堆栈帧时,堆栈上实际传递的char
后的数据等于零浮点值。在对printf
的第二次调用中,生成了一个新的堆栈帧,可能覆盖了第一次调用所覆盖的相同空间。在这种情况下,会出现一个完整的double
值,并按预期进行打印。当函数返回时,堆栈帧被“销毁”。为了提高效率,当函数返回且内容保持不变时,堆栈帧通常不会归零。在第三次调用printf
时,再次传递一个字节,而要求printf
将sizeof(double)
字节解释为浮点值。上一次调用printf
的堆栈帧现在包含上一次调用传递的double
的值,其中一个字节被新参数的字节覆盖,从而打印出值
如果我将您的第二个printf
呼叫更改为:
printf("\nValue of a=%f", 1.234);
第三次调用printf
打印(在我的系统上):
这似乎验证了上述逻辑
总之,您要求
printf
从堆栈中读取的数据比实际传递给函数的数据多,因此,结果是未定义的。在您的情况下,读取的数据是以前调用的剩余数据,这解释了您在特定平台上得到的结果。(正如Ray指出的,参数的实际传递方式可能会有所不同,因为这取决于实现。一些系统会在寄存器中传递值,但点保持不变。)我得到的答案与您的答案略有不同(http://ideone.com/RG4uq)这并不奇怪,因为混合浮点和积分类型的变量函数的行为是未定义的
下面是正在发生的事情。假设记忆
50000000 c3 f5 48 40 (a)
50000004 00 01 00 00 (b)
50000008 00 00 00 50 (p)
5000000c 04 00 00 50 (p1)