将 int* 转换为 const short int*

Cast int* to const short int*

本文关键字:int short const 转换      更新时间:2023-10-16

我正在使用库中的函数,其中最重要的函数采用 const short int* 类型的参数。相反,我所拥有的是int *,并且想知道是否有一种方法可以将int *投射到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 = %hdn", 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. 尝试了恒定性演员表。函数调用如下所示:

    disp(const_cast<const short*> arr, len);这导致编译时出错。

我的问题:
1. 为什么方法 1 中的输出如此奇怪?那边是怎么回事?
2. 我看到一些示例,这些示例使用方法 2 中的常量转换来消除常量。我不知道如何添加相同的内容。
3. 有没有办法将int*投射到const short int*

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

通常,从 int * 转换为 short * 不会提供有用的行为(事实上,如果您尝试取消引用生成的指针,可能会导致未定义的行为)。 它们是指向根本不同类型的指针。

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

铸件几乎总是设计问题的标志。如果你有一个接受short*的函数(const或其他),你需要用short*调用它。因此,与其分配一个int数组,不如分配一个short数组。

当您将int*强制转换为short*时,您告诉编译器假装int*实际上是指向short的指针。它会这样做,但是对编译器撒谎后,您要对后果负责。

对,所以在许多环境中,short的 SIZE 与int不同(不一定是这样,而且肯定有编译器,例如具有 16 位int和 16 位short)。

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

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

编辑:请注意,由于指针是"大小相关的",如果您将一种大小的指针投射到指向不同大小类型的指针,则数据的对齐将是错误的,这就是为什么输出中所有其他值均为零的原因 - 因为int是 4 个字节 [通常] 和一个short是 2 个字节, 指针将为每个索引"步进"2 个字节,(因此arr[i]将是原始arr + i * 2 字节。 其中int * arr的"步长"为 4 个字节,因此 arr + i * 4 个字节。根据您的整数值,您将从中获得一些"半个整数"值 - 由于您的数字很小,因此为零。

因此,当编译器完全按照您的要求进行操作时:使指针指向short指向包含int的内存块,但它不会执行您期望它执行的操作,即将每个int转换为short。为此,您必须执行以下操作:

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]);
}

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

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

对 q.1
的回答输出一点也不奇怪。显然,您的编译器为每个int分配 4 个字节,每个short 2 个字节。因此,您的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
...

当您将arr转换为short时,内存现在被"分组"为2个字节:

0

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

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

对问题2
的答复函数displayconst的声明仅表示arr的内容在执行display过程中不会改变。您无需将参数显式转换为数组const即可调用display

对问题3
的答复请按@Pete和@Mats查看答案