【问题标题】:Cast int* to const short int*将 int* 转换为 const short int*
【发布时间】:2013-01-19 06:34:02
【问题描述】:

我正在使用库中的函数,其中最重要的函数采用const short int* 类型的参数。我所拥有的是int *,我想知道是否有办法将int * 转换为const short int*。以下代码 sn -p 突出显示了我面临的问题:

/* 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;
    }

上面的代码sn -p 编译。 这是我迄今为止尝试过的:
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&lt;const short*&gt; arr, len);
    这导致编译时出错。

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

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

【问题讨论】:

  • 你的目标应该是从你的代码中移除强制转换。
  • 虽然我已经写了一个类似的答案,但如果您解释了您实际想要实现的目标,它可能会有所帮助 - 这听起来像是一个 XY 问题,您想做 X,您认为应该这样做由 Y 解决,因此您询问 Y。

标签: c++ pointers casting int


【解决方案1】:

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

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

【讨论】:

  • 好的。但是当它期望const short* 产生问题时不会通过short*?我还没有尝试过,我会的..但想问你。
  • @Sriram:不,将T * 传递给期望const T * 的东西完全没问题(你甚至不需要显式转换)。反过来,这可能会出现问题。
  • 将非const 传递给const 期望函数是可以的。 const 关键字有时用于函数定义中,表示特定函数不会更改您给它的参数。例如,查看printf 的定义,它将format 参数声明为const char*
【解决方案2】:

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

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

【讨论】:

  • “演员表几乎总是设计问题的标志” - 我不同意这一点,当你知道你在做什么时,它是有用且强大的功能。
  • 这取决于案件的类型,不是吗?我看不出使用static_cast 将窄算术类型转换为更宽算术类型,或将int 转换为doubled 有任何问题。另一方面,指针转换是一个不同的问题,我同意你的看法。
  • "static_cast 将窄算术类型转换为宽算术类型":也就是说,添加一个显式转换来告诉编译器进行安全、明确定义的转换,无论如何它都会这样做?这样的强制转换没有任何好处,并且可能掩盖在以后的维护周期中引入的问题。
  • 我能想到的一个系统异常是从基类指针向下转换。
  • @Agentlien - 即便如此。 &lt;g&gt; 在大多数情况下,需要在层次结构中进行转换表明存在设计问题。偶尔也可以,但是对于初学者来说,更严格的规则是合适的:不要使用强制类型转换。
【解决方案3】:

是的,所以 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.

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

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

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

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

在这两种情况下,不要忘记在不再需要数组时释放它。

【讨论】:

  • 代码 sn-p 反映了precisely 我正在尝试做的事情。想办法将int* 转换为const short int*
  • 好吧,那么您的代码运行良好 - 除非存在您的问题中没有描述的某种问题。
  • 编辑了问题。请让我知道这是否使它更“透明”。
  • 我已经编辑了我的回复来回答我认为是你的问题。
【解决方案4】:

回答 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。

回答 q.2
在函数display中声明const只意味着arr的内容在display的执行过程中不会改变。您无需将参数显式转换为 const 数组即可调用 display

回答 q.3
请查看@Pete 和@Mats 的回答

【讨论】:

    猜你喜欢
    • 2020-12-14
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 2015-01-20
    相关资源
    最近更新 更多