0

我正在研究使用 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!这怎么可能?

此外,假设我想创建一个接受“数字”(即浮点数、整数、双精度、浮点数或其他任何值(例如,甚至 u_short))并在其上加 1 的方法。最通用的实现可能是什么?我应该考虑以下原型:

void add_one(void* x);

?

4

4 回答 4

3
float *p = 1;

是无效的; 您的编译器至少应该发出警告。它尝试float*使用整数表达式(类型int、值)初始化指针变量(类型1)。

int标准 C 中没有从to的隐式转换float*

如果您的编译器警告您该行,请注意警告。如果没有,请使用您的编译器选项直到它出现,或者获得更好(更现代?)的编译器。

至于一个函数,它接受一个指向变量的指针,不管它的类型如何,都给它加 1,在 C 中真的没有办法做到这一点。可以想象,你可以编写一个函数,它接受一个void*指针和一个指示其类型的第二个参数,然后使用switch函数中的语句来决定要执行的转换。但是写起来要容易得多

x ++;

针对您更新的问题:

float *p;

这是有效的;它定义p为指向float.

*p = 1.0f;

编译器可能不会抱怨这一点,但由于您没有为 赋值p,它可能没有指向有效对象。*p = 1.0f;具有未定义的行为。如果你幸运的话,你的程序会崩溃;如果你不走运,它似乎会起作用。

于 2013-01-23T01:52:39.813 回答
1

首先,我必须说清楚一点。float *pfloat* p是等价的陈述。如果你是 C 的初学者,我建议你写后者而不是前者,因为这样可以更清楚地说明类型是什么,变量是什么——它会在以后为你省去很多困惑。考虑到这一点,请记住,在下面的块p中,not*p是变量。

float* p;
*p = 1.0f;

第一行在float*堆栈上分配 a 。就像在堆栈上分配的所有变量一样,它的初始值是未定义的(很可能是垃圾)。这不是指针独有的:即使你分配了一个int并且你没有初始化它,它也会有一个未定义的值。

也会发生同样的情况p,因此您p最初应该将其视为包含随机数据。如果p包含随机数据并且它是一个指针,则意味着它指向一个随机地址。尝试(在第二行中)将值1.0f(或其他任何内容)写入该随机地址几乎总是会导致分段错误,因为在任何给定时间随机地址属于您的程序的可能性很小。

于 2013-01-23T02:06:13.443 回答
1

float *p中,p 是一个指向浮点数的指针。*p = 1.0如果不先让指针 p 指向某个东西,你就不能说。例如,

float *p = new float;
*p = 1.0f;

那可能行得通。

于 2013-01-23T02:01:10.360 回答
1

通过声明

float *p;

p 应该是保存有效浮点变量地址的指针。在这里,您只是为 p 分配一个数字。

*p = 1.0f;

这将导致未定义的行为。因为 p 不包含任何有效地址,而您只是试图取消引用它。

于 2013-01-23T01:57:03.710 回答