关于C#:将int *转换为const short int *

 2021-04-26 

Cast int* to const short int*

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* 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\
"
, 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)。结果输出很奇怪:

1
2
3
4
5
6
7
8
9
10
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
  • 尝试了const-ness演员表。函数调用看起来像:
    disp(const_cast<const short*> arr, len);
    这导致在编译时出错。
  • 我的问题:
    1.为什么方法1中的输出如此奇怪?那边发生了什么事?
    2.我看到了一些使用方法2中的const删除const-ness的示例。我不知道如何添加相同的内容。
    3.是否可以将int*转换为const short int*

    P.S:如果以前曾提出过此类问题,请告诉我。我用谷歌搜索,没有发现任何具体信息。


    通常,从int *强制转换为short *不会产生有用的行为(实际上,如果尝试取消对结果指针的引用,可能会导致未定义的行为)。它们是根本不同类型的指针。

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


    发布几乎总是设计问题的征兆。如果您有一个采用short*(const或其他方式)的函数,则需要使用short*进行调用。因此,代替分配int的数组,而是分配short的数组。

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


    对,因此short的大小在许多环境中与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。为此,您要么必须做:

    1
    2
    3
    4
    5
    6
    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.
    }

    如果这给出了错误的一半,则可以执行以下操作:

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

    但是它取决于"字节顺序"(大字节序或小字节序),因此它不是可移植的。在通用代码中执行此操作非常糟糕。

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

    1
    2
    3
    4
    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个问题
    函数display中的const声明仅表示arr的内容在执行display期间不会更改。您无需显式将参数强制转换为const数组即可调用display

    回答第3个问题
    请查看@Pete和@Mats

    的答案