【问题标题】:void* casting get unexpected outputvoid* 铸造得到意外的输出
【发布时间】:2018-01-06 17:21:44
【问题描述】:
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* 指针转换有问题,但我不知道为什么。有人可以帮忙吗?

【问题讨论】:

  • 你返回一个指向局部变量的指针。一旦函数退出,局部变量就会超出范围,并且不再存在。指向此类局部变量的指针将变为无效。尝试取消引用该指针将导致undefined behavior。你取消引用四个这样的无效指针。总之,问题与你的选角无关。
  • 当你返回并使用p时,整个程序的行为是不确定的。
  • 顺便问一下,您尝试使用void* 演员解决的实际 问题是什么?你为什么这样做?在 C++ 中,您很少需要 void*。而且我也没有看到任何特殊需要为结构成员使用指针。
  • 谢谢,如果我为这些局部变量动态分配一些内存,会解决这个问题吗?

标签: c++ c++11 casting void-pointers


【解决方案1】:

你用这个创建了未定义的行为:

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

在那里,您使用指向create自动存储范围(又名局部变量)中的对象的指针来初始化mystruct。这些对象在返回 create 的那一刻就不再存在,因此指针变得无效。此外,您还将在 create 函数内返回指向 mystruct 自动存储对象的指针。所以这是在未定义行为之上调用未定义行为。

编辑建议的解决方案:

停止在结构中使用指针。无论如何,传递指向intfloat 的指针是没有意义的,因为指针总是大于。如果您传递指针或指向函数的指针,则将通过复制值来传递,但使用指针时会有一个额外的间接步骤。如果您想使用它们来传递函数可以更改值的“引用”,那么传递指向数字类型的指针是有意义的。

传递指向结构的指针也很有意义,这样就不必复制整个结构。

所以我建议你完全摆脱指针。您显然还不了解它们是如何工作的,而且对于您在那里的特定任务,它们无论如何都是错误的工具。

【讨论】:

  • @JHBonarius 指针的大小取决于平台(从技术上讲,intfloat 的大小也没有准确指定)。添加到这个答案:你几乎不需要 C++ 中的原始指针(除非你想做一些高级的低级编程)。按值存储变量、在std::vector 中存储数组以及通过引用传递对象应该涵盖 99% 的初学者用例
  • @JHBonarius:在 32 位机器浮点数上,int 和指针都是 32 位。在遵循标准 ABI 之一的 64 位机器(目前是大多数机器)上,float 和 int 仍然是 32 位,但指针是 64 位(长整数是 64 位,通常是 64 位 ABI,即Windows、Linux 和 *BSD)。如果您希望整数绝对是 64 位,则必须使用 int64_t 或 long long。
猜你喜欢
  • 2011-10-31
  • 1970-01-01
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 2023-01-08
相关资源
最近更新 更多