2011-09-10 10 views
1
#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
using namespace std; 

int width = 100; 
int height = 100; 

float cam[] = {-1.1,-1.0,1.2}; 
float D[] = {0.2,0.2,-0.2}; 
float U[] = {0.0,1.0,0.0}; 

float* cross(float* v1,float* v2) 
{ 
    float el1[] = {(v1[1]*v2[2]-v1[2]*v2[1]),(v1[2]*v2[0]-v1[0]*v2[2]),(v1[0]*v2[1]-v1[1]*v2[0])}; 
    return el1; 
} 

float* neg3(float* v) 
{ 
    float arr[3]; 
    for(int i=0;i<3;i++) 
    arr[i] = 0.0-(v[i]); 

    return arr; 
} 

/* 

float* cam_space(float* p) 
{ 
    float* e1 = cross(D,U); 
    float* e2 = cross(D,cross(U,D)); 
    float* e3_n = D; 

    float ar[4]; 
    ar[0] = e1[0]*p[0]+e1[1]*p[1]+e1[2]*p[2]; 
    ar[1] = e2[0]*p[0]+e2[1]*p[1]+e2[2]*p[2]; 
    ar[2] = -(e3_n[0]*p[0]+e3_n[1]*p[1]+e3_n[2]*p[2]); 
    ar[3] = p[3]; 
    return ar; 
} 

*/ 
float* translate(float* p,float* v) 
{ 

    float arr1[3]; 
    for(int i=0;i<=2;i++) 
    arr1[i] = p[i] + v[i]; 

    return arr1; 
} 


int main() 
{ 
    float* poi; 
    poi = cam; //undo later 

    float* nc; 
    nc = neg3(cam); 
    cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl; 


    float arbit[3] = {0.1,0.1,0.1}; 

    float* temp1; 
    temp1 = translate(poi,arbit); 
    //float* temp2; 
    //temp2 = cam_space(temp); 

    cout<<" "<<nc[0]<<" "<<nc[1]<<" "<<nc[2]<<endl; 
    cout<<" "<<poi[0]<<" "<<poi[1]<<" "<<poi[2]<<endl; 


    cout<<" "<<temp1[0]<<" "<<temp1[1]<<" "<<temp1[2]<<endl; 
    return 0; 
} 

ご覧のとおり、ncを2回出力しています。しかし、両方の値が異なります。 2回目のncが表示され、実際にはtemp1の値が表示され、temp1には実際にはガーベッジ値が表示されます。 ヘルプがありますか?C++ポインタと配列

+0

あなたはSTDLIBやstdio関数を使用していないので、ヘッダを取り除く:

が、この考えてみましょう。また将来的には、ここで言及した推論のためにcstdlibとcstdioを使用することもできます。http://stackoverflow.com/questions/2847729/whats-the-main-difference-between-stdlib-h-and-cstdlib-in- c/2847753#2847753 また、これらのグローバル変数がグローバル定数である場合は、そのようにマークします。 –

+0

他の誰もが言ったこと(+1にすべて)と[アレイは悪い]という事実(http://www.parashift.com/c++-faq-lite/containers.html)。 –

答えて

5
float* translate(float* p,float* v) 
{ 

    float arr1[3]; 
    for(int i=0;i<=2;i++) 
    arr1[i] = p[i] + v[i]; 

    return arr1; 
}// arr1 ceases to exist from this point. 

ローカル変数arr1の参照を返します。スタック上に存在し、関数呼び出しの戻り時に割り当て解除されます。しかし、ごみの価値を生み出している参照を保持しています。代わりにnewnew[] arr1を返してください。完了したらdelete[]を覚えておいてください。

+1

Masheshが正しいです。 'translate(float *、float *)'関数の_scope_(中括弧)内に 'float [] arr1'変数を作成して、関数が実行されている間だけ変数が存在するようにしました。その後、あなたはまだ同じメモリブロックを指していますが、 'arr1'はもうそこに格納されません。詳細については、http://en.wikipedia.org/wiki/Scope_(programming)を参照してください。 – wchargin

+2

どのようなコンパイラを使用していますか、@Arpit? 'g ++'はここで助けになります: '関数 'float * cross(float *、float *)': 警告:ローカル変数 'el1'のアドレスが返されました、 など –

1

translate()は、(配列型から変換された)ローカルポインタを返します。だからtemp1を参照しているので、関数の後に存在しませんtranslate()が返されます。

neg3()も同じです。

C++を使用している場合は、std::vector<float>がそのような問題をすべて解決します。

あなたはこの書くことができます:あなたはfloat[3]を使用しているwhereever std::vectorを使用し、同様に

std::vector<float> translate(const std::vector<float> & p, const std::vector<float> & v) 
{ 
    std::vector<float> vf(3); 
    for(int i=0;i <3;i++) 
     vf[i] = p[i] + v[i]; 
    return vf; //semantically, it returns a copy of the local object. 
} 

を。グローバル変数は使用しないでください。

1

右と中央の左にあるローカル変数へのポインタを返します。これらの変数は、関数本体の最後でスコープから外れ、結果は未定義の動作です。

配列修飾機能を処理する良い方法は、パラメータとして配列を渡すことです:

void modify_me(float arr[]) // or `modify_me(float * arr)`, same thing 
{ 
    arr[0] = 0.5; 
    arr[1] = -2.25; 
} 

int main() 
{ 
    float myarray[2]; 
    modify_me(myarray); // now myarray[0] == 0.5, etc. 

    // ... 
} 

あなたがC++にいるので、あなたも、テンプレートの魔法を使用することができます。

template <unsigned int N> 
void modify_me(float (&arr)[N]) 
{ 
    static_assert(N == 3, "You're doing it wrong!"); // C++11 feature 
    arr[0] = /* ... */ 
} 

現在、サイズ3の自動配列ではないものを呼び出すと、コンパイル時エラーが発生します。

1

ローカル変数へのポインタを返す代わりに、値を返す必要があります。

struct V3 { float data[3]; } 

V3 neg3(V3 v) 
{ 
    for(int i=0;i<3;i++) 
     v.data[i] = -v.data[i]; 
    return v; 
}