I am using functions from a library where a most-important function takes arguments of type const short int*. What I have instead is int * and was wondering if there was a way of casting an int * into a const short int*. The following code snippet highlights the problem I am facing:
/* 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;
}
The above code snippet compiles.
This is what I have tried so far:
1. Tried the c-style cast. Function call looked something like so:
disp((const short*) arr, len). The resulting output was quite weird:
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
- Tried the const-ness cast. Function call looked like:
disp(const_cast<const short*> arr, len);
This resulted in an error while compiling.
My question(s):
1. Why is the output in approach 1 so weird? What is going on over there?
2. I saw some examples that remove const-ness using the const cast in approach 2. I do not know how to add the same.
3. Is there a way to cast an int* into a const short int*?
P.S: If there are questions of this sort that have been asked before, please do let me know. I googled it and did not find anything specific.
Right, so the SIZE of a
shortis different to anintin many environments (it doesn’t have to be, and there are certainly compilers that for example have 16-bitintand 16-bitshort).So what you get out of casting a pointer in this way is, a) undefined behaviour, and b) unless you know exactly what you are doing, probably not what you wanted anyway.
The output from your code looks perfectly fine from what I’d expect, so clearly you are not telling us something about what you are trying to do!
Edit: Note that since pointers are “size-dependant”, if you cast a pointer of one size to a pointer to a type of a different size, the alignment of the data will be wrong, which is why every other value is zero in your output – because an
intis 4 bytes [typically] and ashortis 2 bytes, the pointer will “step” 2 bytes for each index, (soarr[i]will be originalarr+ i * 2 bytes. where theint * arrhas a ‘step’ of 4 bytes, soarr + i * 4bytes. Depending on your integer values, you will get some “half an integer” values out of this – since your numbers are small, this is zero.So, whilst the compiler is doing exactly what you ask it to do: make a pointer to
shortpoint to a lump of memory containingint, it won’t do what you EXPECT it to do, namely translate eachintinto ashort. To do that, you will either have to do:If this gives the wrong half, you can do this:
But it depends on the “byte-order” (big endian or little endian) so it’s not portable. And it’s very bad coding style to do this in general code.
Or:
short *sarr = malloc(sizof(short *) * 10);
The second method works in the sense that it makes a copy of your integer array into a short array. This also doesn’t depend on the order the content is stored, or anything like that. Of course, if the value in
arr[i]is greater than what can fit in ashort, you don’t get the same value asarr[i]in yourshort!And in both cases don’t forget to free your array when it is no longer needed.