0

I am studying functions that accept arguments of arbitrary datatypes using void pointers. Such a function is the following:

void funct(void *a) {
    float *p = a;
    printf("number = %f\n",*p);
}

Here is a successful invocation to funct:

float x = 1.0f;
funct(&x);

x is declared to be a float and then its pointer, namely &x (which is of type float*) is passed to funct; quite straightforward!

There is however yet another way to declare a variable in C and get its pointer. This is:

float *p;
*p = 1.0f;

But then the call funct(&x); returns a Segmentation fault: 11! How is that possible?

Additionally, assume that I want to create a method that accepts a "number" (i.e. float, integer, double, float or anything else (e.g. even u_short)) and adds 1 to it. What would the most versatile implementation possibly be? Should I consider the following prototype:

void add_one(void* x);

?

4

4 に答える 4

3
float *p = 1;

無効です; コンパイラは少なくとも警告を発しているはずです。float*整数式(type int、value )を使用して(typeの)ポインタ変数を初期化しようとします1

標準Cではからintへの暗黙の変換はありませんfloat*

コンパイラがその行について警告した場合は、警告に注意してください。そうでない場合は、そうなるまでコンパイラオプションを試してみるか、より優れた(より新しい?)コンパイラを入手してください。

変数へのポインターを受け取り、その型に関係なく1を追加する関数については、Cでそれを行う方法は実際にはありません。おそらく、void*ポインターとその型を示す2番目の引数を受け取る関数を作成できます。次にswitch、関数でステートメントを使用して、実行する変換を決定します。しかし、書くだけの方がはるかに簡単です

x ++;

更新された質問への回答:

float *p;

それは有効です。pへのポインタとして定義されていますfloat

*p = 1.0f;

コンパイラはおそらくそれについて文句を言うことはありませんが、に値を割り当てていないためp、おそらく有効なオブジェクトを指していません。*p = 1.0f;未定義の動作があります。運が良ければ、プログラムはクラッシュします。運が悪ければ、うまくいくように見えます。

于 2013-01-23T01:52:39.813 に答える
1

宣言することによって

float *p;

pは、有効なfloat変数のアドレスを保持するポインターであると想定されています。ここでは、pに数字を割り当てています。

*p = 1.0f;

これは未定義の動作につながります。pは有効なアドレスを保持しておらず、単にそれを逆参照しようとしているためです。

于 2013-01-23T01:57:03.710 に答える
1

float *p、pはfloatへのポインタです。*p = 1.0最初にポインタpを何かに向けさせずに言うことはできません。例えば、

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

それはうまくいくかもしれません。

于 2013-01-23T02:01:10.360 に答える
1

まず、何かを明確にしなければなりません。float *pおよびfloat* pは同等のステートメントです。Cの初心者の場合は、前者の代わりに後者を作成することをお勧めします。これにより、型と変数が明確になり、将来の混乱を大幅に減らすことができます。そのことを念頭に置いて、次のブロックでは、pではなく*pが変数であることを覚えておいてください。

float* p;
*p = 1.0f;

最初の行はスタックにを割り当てfloat*ます。スタックに割り当てられたすべての変数で発生するため、その初期値は未定義です(おそらくガベージ)。これはポインタに限定されません。を割り当ててint初期化しない場合でも、値は未定義になります。

同じことが、でも発生するため、最初はランダムデータを含むpと考える必要があります。ランダムデータが含まれていて、それがポインタである場合、それはランダムアドレスを指していることを意味pします(2行目で)そのランダムアドレスに値(または他の何か)を書き込もうとすると、ほとんどの場合、セグメンテーション違反が発生します。これは、ランダムアドレスがいつでもプログラムに属する可能性がほとんどないためです。p1.0f

于 2013-01-23T02:06:13.443 に答える