2017-07-31 64 views
0
struct mystruct{ 
    int* x; 
    float *y; 
    string *z; 
    mystruct(int* a,float* b, string *c): x(a), y(b), z(c){} 
}; 
void* create(){ 
    int a = 1; 
    float b = 2.2; 
    string c = "aaa"; 
    mystruct x(&a, &b, &c); 
    void* p = &x; 
    return p; 
} 
void print(void *p){ 
    mystruct* p1 = static_cast<mystruct*>(p); 
    cout << *p1->x << " " << *p1->y << " "<<*p1->z<< endl; 
} 
int main(){ 
    cout << sizeof(mystruct) << endl; 
    void* p1 = create(); 
    print(p1); 
    return 0; 
} 

代碼的輸出是這樣的:24 1 2.76648e + 19 \ 203 \ 304] \ 303fffff \ 204UH \ 211 \ 345H \ 201 \ 354 \ 220H \ 211}。 \ 270H \ 211。 我猜想是這樣的:24 1 2.2 aaa無效*鑄造得到意想不到的輸出

我猜這個void *指針轉換出了問題,但我找不出原因。有人可以幫忙嗎?

+2

您返回指向*局部變量*的指針。一旦函數退出,局部變量超出範圍,並且不再存在。指向這些局部變量的指針將失效。試圖取消引用該指針會導致[*未定義行爲*](http://en.cppreference.com/w/cpp/language/ub)。你解除引用四個這樣的無效指針。總之,這個問題與你的演員無關。 –

+0

當你返回並使用'p'時,你整個程序的行爲是不確定的。 – StoryTeller

+3

https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope?noredirect=1&lq=1 – Mat

回答

4

你這個創建未定義行爲:

void* create(){ 
    int a = 1; 
    float b = 2.2; 
    string c = "aaa"; 
    mystruct x(&a, &b, &c); 
    void* p = &x; 
    return p; 
} 

有你初始化一個mystruct與指針在create自動存儲範圍(又名一個局部變量)對象。這些對象在create返回的時刻不再存在,因此這些指針變得無效。此外,您還返回一個指向create函數內的mystruct自動存儲對象的指針。所以這就是在未定義的行爲之上調用未定義的行爲。這裏

編輯是一個建議的解決方案:使用結構內部指針

停止。無論如何傳遞指向intfloat的指針毫無意義,因爲指針總是會比大。如果你傳遞一個指針或者一個指向函數的指針,那麼通過複製值來傳遞它們,但是通過一個指針就會有一個額外的間接步驟。在傳遞指向數值類型的指針時,如果要使用它們來傳遞函數可以更改值的「引用」,則這是合理的。

傳遞指向結構的指針也是有意義的,因此不需要複製整個結構。

所以我建議你擺脫整個指針。你顯然還不知道它們是如何工作的,對於你在那裏的特定任務,無論如何它們都是錯誤的工具。

+0

?浮點是32位,指針是32位? – JHBonarius

+1

@JHBonarius指針的大小依賴於平臺(從技術上講,int和float的大小並沒有完全指定)。爲了增加這個答案:你幾乎不需要C++中的原始指針(除非你想做一些先進的低級編程)。按值存儲變量,將數組存儲在'std :: vector'中並通過引用傳遞對象應覆蓋99%的初學者用例 – chtz

+1

@JHBonarius:在32位機器上,int和pointer都是32位。在一個64位機器上(這是目前大多數機器)遵循標準ABI之一,然後float和int仍然是32位,但是指針是64位(長整數是64位,通常64位ABI在周圍,即Windows,Linux和* BSD)。如果你想要一個整數爲64位,你必須使用int64_t或long long。 – datenwolf