2017-07-31 68 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