大家好,我正在学习C语言,我正在尝试使用单个char指针打印不同数据类型的值。我几乎可以打印所有数据类型,但打印浮点数有问题。谁能解释为什么这是一个问题?以及如何使用单个指针打印确切的浮点值。很抱歉这个菜鸟问题,如果事实是这样的话。我了解对齐问题。但是确实需要一个解决方案。
更新1->对不起,愚蠢的类型转换。现在考虑更新代码。
更新2->谢谢大家的回答。就像我说的那样,我正在学习C语言,很抱歉语法错误。我不是来自CS背景的人,但是再次感谢您。
#include <stdio.h>
int main()
{
long int a = 10;
char ch = 'a';
float b = 16.89;
unsigned int c = 20;
short int d = 30;
char *p;
p = &a;
printf("Value of a: %d\n", *p);
p = &ch;
printf("Value of ch: %c\n", *p);
p = &b;
printf("Value of b(float): %f\n", *p);
printf("Value of b(decimal): %d\n", (int) *((float*)p));
p = &c;
printf("Value of c: %u\n", *p);
p = &d;
printf("Value of d: %i\n", *p);
return 0;
}
The output of the above program is :-
Value of a: 10
Value of ch: a
Value of b(float): 0.000000
Value of b(decimal): 16
Value of c: 20
Value of d: 30
答案 0 :(得分:2)
这种工作是偶然的。 p
是一个char指针;因此*p
始终是一个字符。
您将地址a
转换为long int *
。它已经是long int *
了,因为您使用了long int
的地址-因此这实际上没有任何作用。然后,将其填充到p
的{{1}}中。在char *
变量中不能保留long int *
;现在是char *
。现在,您和我们大多数人一样,显然是在使用little-endian体系结构的机器上,因此最小字节在前:您的char *
表示为long int a
,而{{1} }读取第一个字节。然后,C的另一个特质开始起作用:所有小于[10, 0, 0, 0]
的整数参数都以*p
的形式传递;因此将字节int
转换为int
并压入堆栈(或在较新架构的ABI中通过整数寄存器处理),然后10
使用{ {1}}格式,期望为int
。
对于printf
,%d
不会读取 first 字节,而是读取 only 字节;其余的都一样。其余整数类型也一样,您足够友善,永远不要超过 255 127(谢谢Antti Haapala!)(否则您会看到意外的结果)。
但是,int
是另外一个故事。浮点数在内存中的表示方式与整数不同。当char ch
读取第一个字节时,它会得到与*p
完全无关的内容-有点像试图通过万花筒来猜测一幅画。第一个字节被扩展为int并传递给函数。在较旧的体系结构中,它将像浮点数一样被读取,但是在current ABIs中,多达四个(MS)或六个(UNIX)整数和浮点参数通过寄存器传递,它甚至不查看(因为它通过整数寄存器传递,但是float b
将查看浮点寄存器)。请记住,这主要是因为您存储指针的方式最终使指针成为*p
。
在16.89
中,您执行了非常不同的操作:将指针放在重要的地方。因此,%f
的值会变成char *
一点;然后您取消引用它,并正确获得decimal(b)
;然后将其转换为p
,最后得到float *
(可以用16.89
打印,所以一切都很好)。
tl; dr:C变量的类型固定不变。您所做的任何类型转换只在不存储它们时才重要-将它们放入变量后,类型即为变量的类型。
答案 1 :(得分:0)
在此示例程序中执行的类型强制转换没有任何意义。
F.e。 p = (long int*)&a;
:a
的类型为long int
,这使得&a
的类型为long int *
。
&a
前面的类型是空操作。
p
的类型为char *
,这使得*p
的类型为char
。 char
值存储在1个字节上。在程序中为256
,a
和c
使用大于d
的值,您会发现它为它们打印了错误的值。
您传递给printf()
的值必须与您使用的格式说明符匹配,否则您将得到意外的结果。传递整数(*p
并使用%f
对其进行格式化不会神奇地进行任何类型转换,而只是强制printf()
以错误的方式解释*p
的位序列并产生意外结果,因为它是undefined behaviour。
答案 2 :(得分:0)
您在这里进行的类型转换
p = (float*)&b;
是隐式强制转换,不是必需的。 &b
已经是float*
类型,不需要强制转换。
您实际上需要在printf
语句中进行强制转换。像这样。
printf("Value of b(float): %f\n", *(float*)p);
在所有其他printf
语句中也需要类似的强制转换。
如果您要打印int
,请使用int
指针,而不要使用char
指针,这是没有什么用的。
答案 3 :(得分:0)
如果printf
期间的类型转换正确,它应该已经工作了
printf("Value of b(float): %f\n", *(float *)p);
float
类型与其他任何整数数据类型的表示方式基本不同,它们基本上遵循floating point standard
现在您的代码中的printf
期望%f
的字符类型为*p
,这里已经引发了未定义的行为 >