【问题标题】:Converting arrays of one type to another将一种类型的数组转换为另一种类型
【发布时间】:2016-10-16 16:34:39
【问题描述】:

基本上我有一个双打数组。我想将此数组传递给一个函数(ProcessData),它将它们视为短整数。正在创建一个短指针并将其指向数组,然后将此指针传递给函数ok(代码1)?

这实际上与创建一个短数组、遍历每个元素并将双精度数组的每个元素转换为一个短数组然后传递短数组指针(代码 2)相同吗?谢谢

//code 1
//.....
short* shortPtr = (short*)doubleArr;
ProcessData(shortPtr);

..

//code 2
//...
short shortArr [ARRSIZE];
int i;
for (i = 0; i < ARRSIZE; i++)
{
    shortArr[i] = (short)doubleArr[i];
}
ProcessData(shortArr);

【问题讨论】:

  • 不,不行。这不是一回事。
  • 这就像说“这是一个双精度序列,但假装它是一个短整数序列。祝你好运。”
  • 如果 double 占用 8 个字节,short 占用 2 个字节,您将把每个 double 分割成 4 个不相关的部分。
  • 另外,请选择一种语言C或C++。
  • 感谢您的回答。这个问题适用于 C 和 C++。我们还在 C++ 中使用数组普通数组。

标签: c++ c arrays pointers casting


【解决方案1】:

您不能像各种 cmet 所说的那样只投射。但是如果你使用迭代器,你可以获得或多或少相同的效果:

void do_something_with_short(short i) {
    /* whatever */
}

template <class Iter>
void do_something(Iter first, Iter last) {
    while (first != last)
        do_something_with_short(*first++);
}

您可以使用迭代器将该模板函数调用到任何算术类型的数组中(实际上,任何可以隐式转换为short 的类型,或者,如果您在调用do_something_with_short 时添加一个强制转换,使用需要强制转换的类型):

double data[10]; // needs to be initialized, of course
do_something(std::begin(data), std::end(data));

【讨论】:

    【解决方案2】:

    不,你不能那样做。至少有一个原因:

    数组是通过索引访问的多个内存分配的连续序列,就像这样

    [----][----][----]
    

    注意方括号内的四个破折号。这表示在 C/C++ 中的大多数情况下,int 的长度四个字节。数组单元格可以通过它们的索引来访问,因为如果我们知道第一个单元格的内存地址 (m) 并且我们知道每个单元格的大小 (c) - 在这种情况下,四个字节,我们可以通过 m + index * c 轻松找到任何索引的内存位置

    [----][----][----]
    ^ array[0]
    
    
    [----][----][----]
     ----  ----  ^ array[2]
    

    从根本上说,这就是为什么在 C/C++ 中可以将指针视为数组的原因,因为当您访问数组时,您基本上是在进行指针运算。

    在大多数情况下,在 C/C++ 中,short 的长度为 2 个字节,因此以相同的方式表示它

    [--][--][--]
    

    如果您创建一个short 指针,并尝试将其用作数组,则预计它会指向类似上述排列的东西。如果你尝试索引它,就会出现问题:如果你处理的是一个short数组,array[2]的位置与m + 2 * index相同,如下所示

    [--][--][--]
     --  --  ^ array[2] (note moving along four bytes)
    

    但是由于我们实际上是在处理一个整数数组,所以会发生以下情况

    [----][----][----]
     ----  ^ array[2] (again moving along four bytes)
    

    这显然是错误的

    【讨论】:

      【解决方案3】:

      不,因为++ptr 实际上做了类似ptr = (char*)ptr + sizeof *ptr 的事情(sizeof (char) 定义为 1)。因此,增加 double 指针(通常)会将其移动 8 个字节,而增加 short 指针只会将其移动 2 个字节。

      【讨论】:

        【解决方案4】:

        假设您的孩子学习钢琴,并且偶尔要求您扫描他们出生于 20 世纪的老师(就像您一样)给他们的sheet music 堆栈。你把这些纸带到你的办公室,然后把它们送到复印机。它创建体面的数字扫描,您的孩子可以在配备触摸屏的钢琴上使用。一切都很顺利,直到有一天孩子给你带来了一套旧的罕见的vinyl records。她迫切希望找到乐谱形式的那些旋律,但要求你至少复制唱片。在音乐方面缺乏经验,你把这些磁盘带到你的办公室,将它们加载到扫描仪的automatic document feeder 中,然后意识到你在……嗯……只有当你听到黑胶唱片在里面破裂的声音时才会意识到愚蠢的机器。即使复印机没有配备 ADF,并且您必须手动将所有原件放在其玻璃平板上,当您将扫描件发送给您的女儿时,您也很难得到应有的赞誉。

        扫描仪并不关心你往里面放了什么——只要它适合里面。它尽了最大的努力,但结果却没有达到预期。但是,如果您先将黑胶唱片交给一位经验丰富的音乐家,让他将它们写成乐谱,那么扫描这些唱片会让您的孩子真正感到高兴。

        在 C++ 中,不同的类型可能会有所不同,以至于打印的纸张与 CD 不同。期望接收shorts 数组的 C++ 函数会将任何字节/位序列作为shorts 数组处理。它并不关心内存区域实际上填充了不同类型的值,具有完全不同的表示,就像扫描仪不关心 ADF 上堆栈的内容一样。假设一个函数将在内部将数组的每个元素从double 转换为short,这与相信影印机包括一个留声机和一个音乐家会自动将黑胶唱片转录成纸张形式是一样的。请注意,后者是现实世界复印机的一种可能设计,其他一些编程语言也可以这样工作。但不是1 C++ 的现有实现。


        1 理论上,一个符合标准的 C/C++ 实现是可能的,它会用语言解释 UB 的所有规定,以支持您问题的相反答案,而不是支持最佳表现。但这对于像 C/C++ 这样的语言来说意义不大。

        【讨论】:

          猜你喜欢
          • 2012-03-28
          • 2011-09-24
          • 1970-01-01
          • 2023-02-07
          • 2020-05-27
          • 1970-01-01
          • 2020-12-02
          • 1970-01-01
          • 2020-12-14
          相关资源
          最近更新 更多