2

我正在使用库中的函数,其中最重要的函数采用 type 的参数const short int*。相反,我所拥有的是int *并且想知道是否有办法将 aint *转换为const short int*. 以下代码片段突出显示了我面临的问题:

/* simple program to convert int* to const short* */


    #include <stdio.h>
    #include <iostream>
    #include <stdlib.h>

    void disp(const short* arr, int len) {

      int i = 0;
      for(i = 0; i < len; i++) {
        printf("ith index = %hd\n", arr[i]);
      }
    }

    int main(int argc, char* argv[]) {

      int len = 10, i = 0;
      int *arr = (int *) malloc(sizeof(int) * len);

      for(i = 0; i < len; i++) {
        arr[i] = i;
      }

      disp(arr, len);

      return 0;
    }

上面的代码片段编译。这是我到目前为止所尝试的:
1. 尝试了 c 风格的演员表。函数调用看起来像这样:
disp((const short*) arr, len). 结果输出很奇怪:

ith index = 0
ith index = 0
ith index = 1
ith index = 0
ith index = 2
ith index = 0
ith index = 3
ith index = 0
ith index = 4
ith index = 0 
  1. 尝试了 const-ness 演员表。函数调用看起来像:
    disp(const_cast<const short*> arr, len);
    这导致编译时出错。

我的问题:
1. 为什么方法 1 的输出如此奇怪?那边是怎么回事?
2. 我看到了一些使用方法 2 中的 const cast 删除 const-ness 的示例。我不知道如何添加相同的内容。
3. 有没有办法把 anint*转换成 a const short int*

PS:如果以前有过此类问题,请告诉我。我用谷歌搜索并没有找到任何具体的东西。

4

4 回答 4

5

一般来说,转换 from int *toshort *不会给出有用的行为(事实上,如果您尝试取消引用结果指针,它可能会导致未定义的行为)。它们是指向根本不同类型的指针。

如果你的函数需要一个指向一堆shorts 的指针,那么这就是你需要给它的。您需要创建一个 数组short,并从原始数组中填充它。

于 2013-02-04T14:28:53.570 回答
4

演员表几乎总是设计问题的标志。如果您有一个接受short*(const或其他) 的函数,则需要使用short*. 因此,与其分配 的数组int,不如分配 的数组short

当您将 anint*转换为 a时short*,您是在告诉编译器假装 theint*确实是指向short. 它会这样做,但是对编译器撒了谎,你要为后果负责。

于 2013-02-04T14:33:29.903 回答
3

是的,所以在许多环境中 a 的 SIZE 与 ashort不同int(它不一定是,并且肯定有编译器,例如具有 16-bitint和 16-bit short)。

因此,以这种方式投射指针的结果是,a) 未定义的行为,b) 除非您确切知道自己在做什么,否则可能不是您想要的。

您的代码输出看起来完全符合我的预期,所以很明显您并没有告诉我们您正在尝试做什么!

编辑:请注意,由于指针是“大小相关的”,如果将一个大小的指针转换为指向不同大小类型的指针,数据的对齐方式将是错误的,这就是为什么其他所有值都为零的原因你的输出 - 因为 anint是 4 个字节 [通常] 并且 ashort是 2 个字节,指针将为每个索引“步进” 2 个字节,(所以arr[i]将是原始arr的 + i * 2 个字节。其中的int * arr'step' 为 4 个字节, 所以arr + i * 4字节。根据你的整数值,你会得到一些“半个整数”值——因为你的数字很小,所以这是零。

因此,尽管编译器正在执行您要求它执行的操作:创建一个指向short包含. 为此,您必须执行以下操作:intintshort

short **sarr = malloc(sizof(short *) * 10); 

for(i = 0; i < 10; i++)
{
    sarr[i] = (short *)(&arr[i]);       // This may well not work, since you get the "wrong half" of the int.
}

如果这给出了错误的一半,您可以这样做:

     sarr[i] = (short *)(&arr[i])+1;      // Get second half of int.

但这取决于“字节顺序”(大端或小端),因此它不可移植。在一般代码中这样做是非常糟糕的编码风格。

或者:short *sarr = malloc(sizof(short *) * 10);

for(i = 0; i < 10; i++)
{
    sarr[i] = (short)(arr[i]);
}

第二种方法的工作原理是将整数数组的副本复制到一个短数组中。这也不取决于内容存储的顺序,或类似的东西。当然,如果 in 的值arr[i]大于 a 可以容纳的值short,则不会得到arr[i]short!

在这两种情况下,不要忘记在不再需要时释放您的阵列。

于 2013-02-04T14:33:38.367 回答
2

回答 q.1
输出一点也不奇怪。显然,您的编译器分配每个int4 个字节和每个short2 个字节。因此,您arr的大小为 10x4 = 40 字节。当您为其分配数字 0..9 时,您在内存中拥有(每个字节一个字符,按 分组int):

0 0 0 0
0 0 0 1
0 0 0 2
0 0 0 3
0 0 0 4
...

当您投射arrshort内存时,现在“分组”为 2 个字节:

0 0
0 0
0 0
0 1
0 0
0 2
0 0
...

我希望你能看到效果,以及为什么你0在分配的数字之间突然有 -s。

对问题2的回答函数中
声明的只是表示在执行过程中不会改变的内容。您无需将参数显式转换为数组即可调用.constdisplayarrdisplayconstdisplay

对 q.3 的回答
请参阅@Pete 和@Mats 的回答

于 2013-02-04T14:53:17.377 回答