我正在研究使用void指针接受任意数据类型的参数的函数。这样的功能如下:
void funct(void *a) {
float *p = a;
printf("number = %f\n",*p);
}
这是对funct
的成功调用:
float x = 1.0f;
funct(&x);
声明 x
为浮点数,然后将其&x
(类型为float*
}的指针传递给funct
;非常简单!
然而,还有另一种方法可以在C中声明一个变量并获取它的指针。这是:
float *p;
*p = 1.0f;
然后调用funct(&x);
会返回Segmentation fault: 11
!怎么可能?
另外,假设我想创建一个接受“数字”的方法(即float,integer,double,float或其他任何东西(例如甚至是u_short))并向其添加1。最通用的实现可能是什么?我应该考虑以下原型:
void add_one(void* x);
答案 0 :(得分:3)
float *p = 1;
无效;你的编译器至少应该发出警告。它尝试使用整数表达式(类型float*
,值int
)初始化指针变量(类型为1
)。
标准C中没有从int
到float*
的隐式转换。
如果您的编译器警告您该行,请注意警告。如果没有,请使用您的编译器选项直到它,或者获得更好的(更现代的?)编译器。
对于一个函数,它接受一个指向变量的指针并向它添加1,而不管它的类型如何,在C中实际上没有办法做到这一点。可以想象,你可以编写一个带有void*
指针的函数。第二个参数指示其类型,然后在函数中使用switch
语句来决定要执行的转换。但是编写
x ++;
回答您的最新问题:
float *p;
这是有效的;它将p
定义为指向float
的指针。
*p = 1.0f;
编译器可能不会抱怨,但由于您没有为p
分配值,因此它可能不会指向有效对象。 *p = 1.0f;
有未定义的行为。如果你很幸运,你的程序会崩溃;如果你运气不好,它似乎会起作用。
答案 1 :(得分:1)
宣布
float *p;
p应该是保存有效float变量地址的指针。在这里你只是在向p。
提供一个数字*p = 1.0f;
这会导致未定义的行为。因为p没有任何有效地址,你只是试图取消引用它。
答案 2 :(得分:1)
在float *p
中,p是指向浮点数的指针。如果没有先使指针p指向某个东西,就不能说*p = 1.0
。例如,
float *p = new float;
*p = 1.0f;
这可能有效。
答案 3 :(得分:1)
首先,我必须说清楚。 float *p
和float* p
是等效的陈述。如果您是C语言的初学者,我建议您编写后者而不是前者,因为它更清楚地说明了类型是什么以及变量是什么 - 它将在未来为您节省很多混乱。考虑到这一点,请记住,在以下块中p
,而不是*p
,是变量。
float* p;
*p = 1.0f;
第一行在堆栈上分配float*
。正如在堆栈上分配的所有变量一样,它的初始值是 undefined (最可能是垃圾)。这不是指针所独有的:即使你分配一个int
并且你没有初始化它,它也会有一个未定义的值。
p
也是如此,因此您应该将p
视为最初包含随机数据。如果p
包含随机数据并且它是指针,则表示它指向到随机地址。尝试(在第二行)将值1.0f
(或其他任何内容)写入该随机地址几乎总是会导致分段错误,因为任何给定时间的随机地址几乎不可能属于您的程序。