无效* C中的怪异

时间:2013-01-23 01:49:58

标签: c pointers void-pointers

我正在研究使用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);

4 个答案:

答案 0 :(得分:3)

float *p = 1;

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

标准C中没有从intfloat*的隐式转换。

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

对于一个函数,它接受一个指向变量的指针并向它添加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 *pfloat* p是等效的陈述。如果您是C语言的初学者,我建议您编写后者而不是前者,因为它更清楚地说明了类型是什么以及变量是什么 - 它将在未来为您节省很多混乱。考虑到这一点,请记住,在以下块中p,而不是*p,是变量。

float* p;
*p = 1.0f;

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

p也是如此,因此您应该将p视为最初包含随机数据。如果p包含随机数据并且它是指针,则表示它指向到随机地址。尝试(在第二行)将值1.0f(或其他任何内容)写入该随机地址几乎总是会导致分段错误,因为任何给定时间的随机地址几乎不可能属于您的程序。