Cast int* to const short int* - c++

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.

In general, casting from int * to short * will not give useful behaviour (in fact, it will probably lead to undefined behaviour if you try to dereference the resulting pointer). They are pointers to fundamentally different types.
If your function expects a pointer to a bunch of shorts, then that's what you'll need to give it. You'll need to create an array of short, and populate it from your original array.

Casts are almost always a sign of a design problem. If you have a function that takes a short* (const or otherwise), you need to call it with a short*. So instead of allocating an array of int, allocate an array of short.
When you cast an int* to a short* you're telling the compiler to pretend that the int* is really a pointer to short. It will do that, but having lied to the compiler, you're responsible for the consequences.

Right, so the SIZE of a short is different to an int in many environments (it doesn't have to be, and there are certainly compilers that for example have 16-bit int and 16-bit short).
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 int is 4 bytes [typically] and a short is 2 bytes, the pointer will "step" 2 bytes for each index, (so arr[i] will be original arr + i * 2 bytes. where the int * arr has a 'step' of 4 bytes, so arr + i * 4 bytes. 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 short point to a lump of memory containing int, it won't do what you EXPECT it to do, namely translate each int into a short. To do that, you will either have to do:
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.
}
If this gives the wrong half, you can do this:
sarr[i] = (short *)(&arr[i])+1; // Get second half of int.
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);
for(i = 0; i < 10; i++)
{
sarr[i] = (short)(arr[i]);
}
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 a short, you don't get the same value as arr[i] in your short!
And in both cases don't forget to free your array when it is no longer needed.

Answer to q.1
The output is not weird at all. Apparently, your compiler assign each int 4 bytes and each short 2 bytes. Therefore, your arr is of size 10x4 = 40 bytes. When you assign numbers 0..9 to it you have in memory (one char per byte, grouped by int ):
0 0 0 0
0 0 0 1
0 0 0 2
0 0 0 3
0 0 0 4
...
When you cast arr to short the memory is now "grouped" into 2 bytes :
0 0
0 0
0 0
0 1
0 0
0 2
0 0
...
I hope you can see the effect, and why you suddenly have 0-s in between the numbers you assigned.
Answer to q.2
The declaration of const in the function display only means that the content of arr will not be changed during the execution of display. You do not need to explicitly cast the argument to const array in order to invoke display.
Answer to q.3
please see answers by #Pete and #Mats

Related

Why does this loop run?

#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main()
{
std::string qaz{};
vector <size_t> index ;
cout <<"qaz: "<<qaz<<" length: "<<qaz.length()<<"\n";
for (size_t i{0}; i<= ( qaz.length()-2);i++ )
{ cout<<"Entered"<<i<<"\n";
cout<<"Exited"<<i<<"\n";}
return 0;
}
//Here qaz is an empty string so qaz.length() == 0 (so qaz.length()-2 == -2) and i is initialized to 0 so I expected that we will not enter the loop. But on running it I find that it goes on in an infinite loop. Why? Please help me with it.
See docs for size_t:
std::size_t is the unsigned integer type of the result of the sizeof operator
(Emphasis mine.)
Furthermore, string::length returns a size_t too1.
But even if that were not the case, when comparing signed values to unsigned values, the signed value is converted to unsigned before the comparison, as explained in this answer.
(size_t)0 - 2 will underflow as size_t is unsigned and therefore its minimum value is zero resulting in a large number which is usually2 either 232-2 or 264-2 depending on the processor architecture. Let's go with the latter, then you will get 18,446,744,073,709,552,000 as result.
Now, looking at the result of 0 <= 18446744073709552000 you can see that zero is clearly less than or equal to 18.4 quintillion, so the loop condition is fulfilled. In fact the loop is not infinite, it will loop exactly 18,446,744,073,709,552,001 times, but it's true you will probably not want to wait for it to finally reach its finishing point.
The solution is to avoid the underflow by comparing i + y <= x instead of i <= x - y3, i.e. i + 2 <= qaz.length(). You will then have 2 <= 0 which is false.
1: Technically, it returns an std::allocator<char>::size_type but that is defined as std::size_t.
2: To be exact, it is SIZE_MAX - (2 - 1) i.e. SIZE_MAX - 1 (see limits). In terms of numeric value, it could also be 216-2 - such as on an ATmega328P microcontroller - or some other value, but on the architectures you get on desktop computers at the current point in time it's most likely one of the two I mentioned. It depends on the width of the std::size_t type. If it's X bits wide, you'd get 2X-n for (size_t)0 - n for 0<n<2X. Since C++11 it is however guaranteed that std::size_t is no less than 16 bits wide.
3: However, in the unlikely case that your length is very large, specifically at least the number calculated above with 2X-2 or larger, this would result in an overflow instead. But in that case your whole logic would be flawed and you'd need a different approach. I think this can't be the case anyway because std::ssize support means that string lengths would have to have one unused bit to be repurposed as sign bit, but I think this answer went down various rabbit holes far enough already.
length() returns unsigned value, which cannot be below zero. 0u - 2 wraps around and becomes very large number.
Use i + 2 <= qaz.length() instead.
The issue is that size_t is unsigned. length() returns the strings size_type which is unsigned and most likely also size_t. When the strings size is <2 then length() -2 wraps around to yield a large unsigned value.
Since C++20 there is std::ssize which returns a signed value. Though you also have to adjust the type of i to get correct number of iterations also when i < -2 is the condition:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main()
{
std::string qaz{};
vector <size_t> index ;
cout <<"qaz: "<<qaz<<" length: "<<qaz.length()<<"\n";
for (int i{0}; i<= ( std::ssize(qaz)-2);i++ )
{
cout<<"Entered"<<i<<"\n";
cout<<"Exited"<<i<<"\n";
}
}
Alternatively stay with unsigneds and use i+2 <= qaz.length().

Decimal to binary output

method that convert decimal to binary:
string toBinary(unsigned int n) {
char binary[33] = {0}; // char array with 0 value in each index
int ix = 32;
do {
binary[--ix] = '0' + n % 2; // adding remainder to specific index
n /= 2; // dividing n with 2
} while (n); // loop until n is not equal to 0
// return a string
return (binary + ix); // but unable to understand this line
}
Can anyone please explain what's happening right here return (binary + ix);
ix is an index into the char array. The function creates the binary string starting with its rightmost bit, near the end of the array, and working its way towards the beginning of the array, creating each bit one at a time.
Therefore, when the last bit is created, ix points to the index of the first, most-significant bit. It's not always going to be at the beginning of the array: specifically it won't be if there were fewer than 32 bits.
"binary + ix" adds the index to the first bit to the start of the char buffer, calculating a pointer to the first bit. Since the function returns a std::string, this is fed to std::string's constructor, which takes the pointer to a literal string and constructs a full std::string object from it, implicitly.
Since ix gets decremented only as long as the loop runs (which changes depending on the magnitude of n), this will truncate the string to not include all of the leading zeros that would be there otherwise.
Also note that you can do this: How to print (using cout) the way a number is stored in memory?

C++ - What happens when you index an array by a float?

I'm trying to understand exactly what happens when indexing through an array with a float value.
This link: Float Values as an index in an Array in C++
Doesn't answer my question, as it states that the float should be rounded to an integer. However in the code I'm trying to evaluate, this answer does not make sense, as the index value would only ever be 0 or 1.
I'm trying to solve a coding challenge posted by Nintendo. To solve the problem there is an archaic statement that uses a bitwise assignment into an array using a long complicated bitwise expression.
The array is declared as a pointer
unsigned int* b = new unsigned int[size / 16]; // <- output tab
Then it's assigned 0's to each element
for (int i = 0; i < size / 16; i++) { // Write size / 16 zeros to b
b[i] = 0;
}
Here's the beginning of the statement.
b[(i + j) / 32] ^= // some crazy bitwise expression
The above sits inside of a nested for loop.
I'm sparing a lot of code here, because I want to solve as much of this problem on my own as possible. But I'm wondering if there is a situation were you would want to iterate through an array like this.
There must be more to it than the float just automatically casting to an int. There hast to be more going on here.
There are no floats here. size is an integer, and 16 is an integer, and consequently size/16 is an integer as well.
Integer division rounds towards zero, so if size is in [0,16), then size/16 == 0. If size is in [16,32), then size/16 == 1, and so on. And if size is in (-16, 0], then size / 16 == 0 as well.
([x,y) is the "half-open" interval from x to y: that is, it contains every number between x and y, and furthermore it includes x but excludes y)
The subscript operator in terms of arrays is syntactic sugar. When you have the following :
class A {...};
A ar[17];
std::cout << ar[3] << std::endl;
Saying ar[3] is no different than saying :
*(ar + 3);
So ar[3.4] is the same as saying
*(ar + 3.4) (1)
From the C++ Standard section 5.7.1 - Additive operators we read that :
(...) For addition, either both operands shall have arithmetic or unscoped enumeration type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral or unscoped enumeration type.
that's why expression (1) causes compilation error.
So, when you index an array by a float you get a compilation error
To answer the question in the title:
#include <stdio.h>
int main(int argc, char** argv) {
int x[5];
int i;
for (i = 0; i < 5; ++i)
x[i] = i;
x[2.5] = 10;
for (i = 0; i < 5; ++i)
printf("%d\n", x[i]);
}
if i compile this with gcc i get a compiler error:
foo.c:10: error: array subscript is not an integer

printing double in binary

In 'Thinking in C++' by Bruce Eckel, there is a program given to print a double value
in binary. (Chapter 3, page no. 189)
int main(int argc, char* argv[])
{
if(argc != 2)
{
cout << "Must provide a number" << endl;
exit(1);
}
double d = atof(argv[1]);
unsigned char* cp = reinterpret_cast<unsigned char*>(&d);
for(int i = sizeof(double); i > 0 ; i -= 2)
{
printBinary(cp[i-1]);
printBinary(cp[i]);
}
}
Here while printing cp[i] when i=8 (assuming double is of 8 bytes), wouldn't it be undefined behaviour?
I mean this code doesn't work as it doesn't print cp[0].
A1: Yes, it would be undefined behaviour when it accesses cp[8].
A2: Yes, it also does not print cp[0].
As shown, it prints bytes 7, 8, 5, 6, 3, 4, 2, 1 of the valid values 0..7. So, if you have copied the code correctly from the book, there is a bug in the book's code. Check the errata page for the book, if there is one.
It is also odd that it unwinds the loop; a simpler formulation is:
for (int i = sizeof(double); i-- > 0; )
printBinary(cp[i]);
There is also, presumably, a good reason for printing the bytes in reverse order; it is not obvious what that would be.
It looks like a typo in the book's code. The second call should probably be printBinary(cp[i-2]).
This is a bit wierd though, because they're reversing the byte order compared to what's actually in memory (IEEE 754 floating point numbers have no rules about endianness, so I guess it's valid on his platform), and because he's counting by 2 instead of just 1.
It would be simpler to write
for(int i = 0; i != sizeof(double) ; ++i) printBinary(cp[i]);
or (if reversing the bytes is important) use the standard idiom for a loop that counts down
for(int i = sizeof(double); (i--) > 0;) printBinary(cp[i]);
You can do this in an endian-independent way, by casting the double to an unsigned long long. Then you can use simple bit shifting on the integer to access and print the bits, from bit 0 to bit 63.
(I've written a C function called "print_raw_double_binary() that does this -- see my article Displaying the Raw Fields of a Floating-Point Number for details.)

Assigning multiple integers to a character array in binary

I have three integers (4 bytes of memory for each integer) and I want to assign each of their binary values to a character array with 12 elements. So, if each integer had a value of let's say 2, then I want the character array to have these values:
2 0 0 0 2 0 0 0 2 0 0 0
I have tried:
memcpy(cTemp, &integer1 + &integer2 + &integer3, 12);
but I receive an "invalid operands" compiler error.
I have also found the function strcat referenced here: http://www.cplusplus.com/reference/clibrary/cstring/
However it is mentioned as: "The terminating null character in destination is overwritten by the first character of source" which I obviously don't want since most of the times integers will have a null character at the end unless the value is really large. Does anybody know of a better working method? Any help is appreciated.
It is probably simpler (if you are on a x86 at least :P) to just cast the pointer and assign directly. i.e.
int* p = (int*) cTemp;
p[0] = a;
p[1] = b;
p[2] = c;
You can also do a union hack:
union translate {
char c[sizeof(int) * 3];
int i[3];
};
translate t;
t.i[0] = 2;
t.i[1] = 2;
t.i[2] = 2;
// access t.c[x] to get the chars
... and read the chars...
If you want to see how a variable is represented as a sequence of bytes, you can do the following.
int i[3] = {2, 2, 2};
char cTemp[sizeof i];
memcpy(cTemp, &i, sizeof i);
Note however that the representation will be different on different platforms. What are you trying to solve?
Edit:
I'm just writing a program to edit [a file], and the file happens to store integers in binary.
Why didn't you say so in the first place? If you know the program will only run on platforms where int has the correct memory-layout, you can simply store the integer.
fout.write((char const *)&i, sizeof i);
However, if you want to be portable, you need to properly serialize it.
void store_uint32_le(char * dest, unsigned long value)
{
for (int i = 0; i < 4; ++i)
{
*dest++ = value & 0xff;
value >>= 8;
}
assert(value == 0);
}
int main()
{
char serialized[12];
store_uint32_le(serialized, 2);
store_uint32_le(serialized + 4, 2);
store_uint32_le(serialized + 8, 2);
std::ofstream fout("myfile.bin", std::ios::binary);
fout.write(serialized, sizeof serialized);
}
I think this should work:
int i,j,k;
char a[12];
*((int*)a) = i;
*(((int*)a)+1) = j;
*(((int*)a)+2) = k;