【问题标题】:C++ Cast from ‘std::__tuple... {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision从‘std::__tuple...{aka ‘unsigned int*’} 到 ‘uint32_t’ {aka ‘unsigned int’} 的 C++ Cast 失去精度
【发布时间】:2021-04-14 16:20:54
【问题描述】:

您可能需要原谅我,因为我是 C++ 新手,并且可能在我目前编写的代码中犯了一些基本错误。

static tuple<read_result, uint8_t*> m_scan_record(bool skip, uint32_t& size, FILE* file)
{
    read_result result;
    
    tuple<read_result, uint32_t*> rd_rec_size_result = m_read_generic_t<uint32_t>(file);

    result = (read_result)get<0>(rd_rec_size_result);
    
    if (result != read_success )
    {
        return tuple<read_result, uint8_t*>(result, nullptr);
    }

    size = (uint32_t) get<1>(rd_rec_size_result);

    if ( skip )
    {
        fseek(file, size, SEEK_CUR);
    }
// ...
}

template<typename T>
static tuple<read_result, T*> m_read_generic_t(FILE* file)
{
    T ret = 0;
    
    read_result result = m_read_from_file_to_buffer(&ret, sizeof(T), file);

    if (result == read_success)
    {
        return tuple<read_result, T*>(result, &ret);
    }

    return tuple<read_result, T*>(result, nullptr);
}

当我编译这段代码时,我得到了这个错误:

cast from ‘std::__tuple_element_t<1, std::tuple<read_result, unsigned int*> >’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]

我的意图和我应该做/发生的事情:

  1. m_scan_record 的声明中,size 参数是用&amp; 声明的,它允许我通过引用传递值,类似于使用REF c# 关键字

  2. 我调用了泛型(模板)函数m_read_generic_t,它使用指定类型&lt;unit32_t&gt; 调用,因此(根据其定义)将返回tuple&lt;read_result, uint32_t*&gt; 类型

  3. 一旦我得到m_read_generic_t 返回的元组,我想获取元组的第二个值所指向的unit32_t 值,并将该值放入上面第1 点提到的size 变量中,然后调用函数可能会在堆栈的上一级访问它。

  4. 从以上几点你可以希望看到我的意图(我很感激我在现实中可能很遥远!)是在这一行:

    size = (uint32_t) get(rd_rec_size_result);

我所做的只是获取一个“指向”值并将其放入匹配类型的变量中,就像经常引用的教科书示例一样:

uint32_t v = 123;
uint32_t* ptr_to_v = &v;
uint32_t x = ptr_to_v;   // x == 123

很明显,这不是我的代码真正发生的事情,因为如果是这样,我认为演员将是不需要的。但如果我删除它,像这样:

size = get<1>(rd_rec_size_result);

然后我得到一个编译时错误:

a value of type "std::__tuple_element_t<1UL, std::tuple<read_result, uint32_t *>>" cannot be assigned to an entity of type "uint32_t"

因此,我相信我做错了什么——但我不知道是什么。这与我将指针从元组中取出的方式有关吗?或者在从 uint32_t* 获取 uint32_t 值时还有其他事情发生吗?

这一切都在 Ubuntu 20.04 上的 C++ 环境中,FWIW

非常感谢您提供任何/所有建议;请放开我!

【问题讨论】:

  • 您至少遗漏了read_result 的定义,这似乎是核心。请发送minimal reproducible example。您还有一些 C 类型的强制转换。为什么需要它们?我没有看到任何要求在任何地方使用这种类型的铸造的东西。我也看不出使用uint32_t 的理由。为什么不使用函数返回的类型?

标签: c++ pointers precision stdtuple uint32


【解决方案1】:
tuple<read_result, uint32_t*> rd_rec_size_result = ...

这个元组的第二个成员,正如这里明确声明的,是一个指向uint32_t 的指针。这就是 uint32_t * 在 C++ 中的含义。

size = (uint32_t) get<1>(rd_rec_size_result);

这会检索uint32_t * 并尝试将其转换为uint32_t。 C++ 不能以这种方式工作。虽然这种转换可能是强制的,但你的编译器完全有权利相信无论这段代码试图做什么,它一定是错误的。

也许我最初想知道,您的意图是取消引用指针。无论如何,这就是您的编译错误的原因。如果您的意图是,真正地,取消引用这个指针,那么这将是一个简单的问题,将其更改为

size = *get<1>(rd_rec_size_result);

但是,这不会是您的麻烦的终结。即使修复了这个编译错误,这样,显示的代码仍然会被严重破坏。

这是因为m_read_generic_t返回一个指向本地对象的指针,当函数返回时该对象将被销毁,并且尝试取消引用该指针,在这里,将生成demons fly out of your nose

真正的解决方法是将m_read_generic_t更改为首先返回一个指针作为元组中的第二个值,从而从一开始就消除了编译错误。

【讨论】:

  • 我了解 Sam - 这同时也很有启发性,所以谢谢。我将带着你的观察再次进入代码。我不希望恶魔从我(或其他任何人)的鼻子里出来!!再次感谢。
猜你喜欢
  • 1970-01-01
  • 2019-10-30
  • 2016-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-14
  • 2017-03-02
相关资源
最近更新 更多