我正在使用库中的函数,其中最重要的函数接受类型为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 = %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;
}
上面的代码片段编译。
这是我到目前为止所尝试的:
试过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
disp(const_cast<const short*> arr, len);
我的问题:
1.为什么方法1中的输出如此奇怪?那边发生了什么事?
2.我看到了一些使用方法2中的const cast去除常量的示例。我不知道如何添加相同的内容
3.有没有办法将int*
投射到const short int*
?
答案 0 :(得分:5)
通常,从int *
转换为short *
不会产生有用的行为(实际上,如果您尝试取消引用生成的指针,它可能会导致未定义的行为)。它们指向基本不同的类型。
如果你的函数需要指向一堆short
的指针,那么你需要给它。您需要创建一个short
数组,并从原始数组中填充它。
答案 1 :(得分:4)
演员表几乎总是设计问题的标志。如果您的某个功能需要short*
(const
或其他),则需要使用short*
进行调用。因此,不是分配int
数组,而是分配一个short
数组。
当您将int*
转换为short*
时,您告诉编译器假装int*
实际上是指向short
的指针。它会这样做,但是对编译器撒了谎,你要承担后果。
答案 2 :(得分:3)
是的,所以short
的SIZE与许多环境中的int
不同(它不一定是,并且肯定有编译器例如具有16位{{} 1}}和16位int
)。
所以你以这种方式投射指针的方法是:a)未定义的行为,b)除非你确切地知道你在做什么,否则可能不是你想要的。
你的代码的输出看起来非常好,我所期待的很明显,你没有告诉我们你想要做什么!
编辑:请注意,由于指针是“与大小相关的”,如果将一个大小的指针强制转换为指向不同大小类型的指针,则数据的对齐将是错误的,这就是为什么每隔一个值在输出中为零 - 因为short
是4个字节[通常]而int
是2个字节,指针将“逐步”为每个索引2个字节,(所以short
将原始arr[i]
+ i * 2个字节。其中arr
的'step'为4个字节,所以int * arr
个字节。根据你的整数值,你会得到一些“半个整数“这个值 - 因为你的数字很小,这是零。
所以,虽然编译器完全按照你的要求去做:把一个指向arr + i * 4
的指针指向一个包含short
的内存块,它不会做你想象的那样do,即将每个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.
}
但它取决于“字节顺序”(大端或小端),因此它不可移植。在一般代码中执行此操作是非常糟糕的编码风格。
或者: short * sarr = malloc(sizof(short *)* 10);
sarr[i] = (short *)(&arr[i])+1; // Get second half of int.
第二种方法的作用是将整数数组的副本复制成一个短数组。这也不依赖于内容的存储顺序或类似的内容。当然,如果for(i = 0; i < 10; i++)
{
sarr[i] = (short)(arr[i]);
}
中的值大于arr[i]
中的值,则short
中的值不会与arr[i]
的值相同!
在这两种情况下,不要忘记在不再需要时释放阵列。
答案 3 :(得分:2)
回答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
函数const
中的display
声明仅表示在执行arr
期间display
的内容不会更改。您无需将参数显式转换为const
数组,以便调用display
。
回答q.3
请查看@Pete和@Mats