I was having a small play around with C++ today and came across this which I thought was odd, but perhaps more likely due to a misunderstanding by me and lack of pure C coding recently.
What I was looking to do originally was convert a double into an array of unsigned chars. My understanding was that the 64 bits of the double (sizeof(double) is 8) would now be represented as 8 8-bit chars. To do this I was using reinterpret_cast.
So here's some code to convert from double to char array, or at least I thought that's what it was doing. Problem was it was returning 15 from strlen instead of 8, why I'm not sure.
double d = 0.3;
unsigned char *c = reinterpret_cast<unsigned char*> ( &d );
std::cout << strlen( (char*)c ) << std::endl;
So the strlen was my first issue. But then I tried the following and found that it returned 11, 19, 27, 35. The difference between these numbers is 8 so on some level something right is going on. But why does this not return 15, 15, 15, 15, ( as it was returning 15 in the code above ).
double d = 0.3;
double d1 = 0.3;
double d2 = 0.3;
double d3 = 0.3;
unsigned char *c_d = reinterpret_cast<unsigned char*> ( &d );
unsigned char *c_d1 = reinterpret_cast<unsigned char*> ( &d1 );
unsigned char *c_d2 = reinterpret_cast<unsigned char*> ( &d2 );
unsigned char *c_d3 = reinterpret_cast<unsigned char*> ( &d3 );
std::cout << strlen( (char*)c_d ) << std::endl;
std::cout << strlen( (char*)c_d1 ) << std::endl;
std::cout << strlen( (char*)c_d2 ) << std::endl;
std::cout << strlen( (char*)c_d3 ) << std::endl;
So I looked at the addresses of the chars and they are.
0x28fec4
0x28fec0
0x28febc
0x28feb8
Now this makes sense given that the size of an unsigned char* on my system is 4 bytes, but I thought the correct amount of memory would be allocated from the cast, otherwise it seems like reinterpret_cast is a pretty dangerous thing... Furthermore if I do
for (int i = 0; i < 4; ++i) {
double d = 0.3;
unsigned char *c = reinterpret_cast<unsigned char*> ( &d );
std::cout << strlen( (char*)c ) << std::endl;
}
This prints 11, 11, 11, 11!
So what is going on here, clearly memory is getting overwritten in places and reinterpret cast is not working as I thought it would (i.e. I'm using it wrong). Having been using strings for so long in C++, sometimes when you go back to raw char arrays, you forget these things.
So I suppose this is a 3 part question.
Why was strlen initially returning 15?
Why did the 4 strlen calls grow in size?
Why did the loop return 11, 11, 11, 11?
Thanks.
strlen works by iterating through the array that it assumes the passed const char* points at until it finds a char with value 0. This is the null-terminating character that is automatically added to the end of string literals. The bytes that make up the value representation of your double do not end with a null character. The strlen will just keep going past the end of your double object until it finds a byte with value 0.
Consider the string literal "Hello". In memory, with an ASCII compatible execution character set, this will be stored as the following bytes (in hexadecimal):
48 65 6c 6c 6f 00
strlen would read through each of them until it found the byte with value 0 and report how many bytes it has seen so far.
The IEEE 754 double precision representation of 0.3 is:
3F D3 33 33 33 33 33 33
As you can see, there is no byte with value 0, so strlen just won't know when to stop.
Whatever value the function returns is probably just how far it got until it found a 0 in memory, but you've already hit undefined behaviour and so making any guesses about it is pointless.
Your problem is your use of strlen( (char*)c ), because strlen expects a pointer to a null-terminated character string.
It seems like you're expecting some sort of "boundary" between the 8th and 9th byte, since those first 8 bytes were originally a double.
That information is lost once you've cast that memory to a char*. It becomes the responsibility of your code to know how many chars are valid.
A couple of things:
sizeof(double) probably isn't 4. It's usually 8. Use the operator instead of a hard-coded assumption.
The pointer reinterpret_cast<unsigned char*>(&d) does not indicate a pointer to a null-terminated "string". strlen operates by iterating until it finds a null. You're into undefined behavior there.
Related
If I want to compile the following code:
int x = 8;
int y = 17;
char final[2];
final[0] = (char) x;
final[1] = (char) y%10;
cout << final[0] << final[1] << endl;
It shows nothing. I don't know why? So how can I successfully convert it?
(char)8 is not '8', but the ASCII value 8 (the backspace character). To display the character 8 you can add it to '0':
int x = 8;
int y = 17;
char final[2];
final[0] = '0' + x;
final[1] = '0' + (y%10);
cout << final[0] << final[1] << endl;
As per your program you are printing char 8, and char 7.
They are not printable. In fact they are BELL and Backspace characters respectively.
Just run you program and redirect it to a file.
Then do an hexdump, you will see what is printed.
./a.out > /tmp/b
hd /tmp/b
00000000 08 07 0a |...|
00000003
What you need to understand is that in C++, chars are numbers, just like ints, only in a smaller range. When you cast the integer 8 to char, C++ thinks you want a char holding the number 8. If we look at our handy ASCII table, we can see that 8 is BS (backspace) and 7 is BEL (which sometimes rings a bell when you print it to a terminal). Neither of those are printable, which is why you aren't seeing anything.
If you just want to print the 87 to standard output, then this code will do that:
cout << x << (y%10) << endl;
If you really need to convert it chars first, then fear not, it can still be done. I'm not much of a C++ person, but this is the way to do it in C:
char final[2];
snprintf(final, sizeof final, "%d%d", x, y % 10);
(See snprintf(3))
This code treats the 2-char array as a string, and writes the two numbers you specified to it using a printf format string. Strings in C normally end with a NUL byte, and if you extended the array to three chars, the final char would be set to NUL. But because we told snprintf how long the string is, it won't write more chars than it can.
This should also work in C++.
I am using Visual C 6
I am trying to convert a character array (single-quotation) into an integer, then incrementing the value by 1, then storing the result back into a different character array..
But I keep getting an unexpected value when converting back to character..
Here is my code
char char_array[4];
char_array[0] = '1';
char_array[1] = '2';
char_array[2] = '3';
char_array[3] = '\0'; //Terminating character
int my_number = atoi(char_array);
printf("my_number = %d" , my_number); // output is 123
my_number++; // works and my_number is incremented =124
printf("now: my_number = %d" , my_number); // output is 124
char result[4]; //declared to store the result
result = itoa(my_number); // Output is unexpected.
printf("%c", result[0]); // Output is 2 instead of 1
printf("%c", result[1]); // Output is 2
printf("%c", result[2]); // Output as 3 instead of 4
It seems that the function itoa() somehow knows the original value 123 and in some weird way knows that I have incremented that value.. but the addition is done to the wrong digit. Instead of adding 1 to the least significant digit, the addition is done to the most significant digit.
I find it really difficult to believe that your compiler is letting this code through:
char result[4]; //declared to store the result
result = itoa(my_number); // Output is unexpected.
For one reason, you're attempting to reseat an array. Which shouldn't be allowed. For another, itoa() normally takes three arguments. It's prototype should look like:
char *itoa(int value, char * str, int base);
So you should be calling it as:
char result[4];
itoa(my_number, result, 10);
Or, if you'd like to use portable functions that don't have possible buffer overflows:
char result[4];
snprintf(result, 4, "%d", my_number);
itoa is not a standard C library function.
You can use
char result[sizeof(int) * CHAR_BIT / 10 * 3 + 4]; // '-1', '\0', max sizeof int on my 4 byte machine
// 10 bits are roughly equal to 3 digits at decimal base, extra 4 for '-', '\0', extra digit and safe character
sprintf(result, "%d", my_number);
If you still want to use itoa, consult the documentation of this function (in library/compiler documentation)
my_number is incremented and hence if you are using itoa() then it will know the new value of my_number which is 124.
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char char_array[4];
char_array[0] = '1';
char_array[1] = '2';
char_array[2] = '3';
char_array[3] = '\0'; //Terminating character
int my_number = atoi(char_array);
printf("my_number = %d" , my_number); // output is 123
my_number++; // works and my_number is incremented =124
printf("now: my_number = %d" , my_number); // output is 124
char result[4]; //declared to store the result
snprintf(result,4,"%d",my_number);
printf("%c", result[0]);
printf("%c", result[1]);
printf("%c", result[2]);
return 0;
}
First the itoa(my_number) maybe wrong, I only know the followed function:
char * itoa ( int value, char * str, int base );
str should be an array long enough to contain any possible value:
(sizeof(int)*8+1) for radix=2 i.e. 17 bytes in 16-bits platforms and
33 in 32-bits platforms.
I cannot figure out why this result in undefined behavoiur or whatever its called?
char ch[10];
strcpy(ch, "street1-3");
char ch2 = ch[6];
cout << ch2 << endl;
int n = (int) ch2;
n = n * 12;
cout << n << endl;
that is cout first prints out position 6 of street1-3 that is "1".
Then when I am trying to typecast this char to an int the value becomes not what its expected to be, that is 12, instead 588.
output in the consolewindow
1
588
What I am doing wrong in the typecasting and how is it solved?
The character '1' doesn't have the ascii value of 1. So (int)'1' != (int)1.
If you look at an ASCII table, you'll see that '1' == 49, and coincidentally (or not...) 49*12 == 588.
There is 2 different behaviour for the operator << on stream with char and int. With char, you get the corresponding character, i.e. "1", wich has a ascii value of 49. So when you do int n = (int)ch2, n has a value of 49, then n * 12 is equal to 588 which is outputed as a value because n is a int.
AS ch2 = 1 , which is of type 'char' , when it is type cast into 'int' , it takes ASKII value of 1 which is 49 and assigns it to 'n' . And 49 * 12 is 588 which is output of your program .
(int)ch2 tells the compiler to interpret the char value in ch2 as an int. Since characters are stored by ascii value, ch2 contains 49, which is what the calculation uses.
Instead of (int)ch2 you should instead use int(ch2), which will perform the conversion you expect.
Oh, and you should always avoid c style casts in c++ where possible - c++ provides a number of safer casts that you should use instead (dynamic,static,etc).
long double i, *ptr;
ptr = &i;
I want to modify the value of byte No. 4. Size of long double is 8 byte. So is it possible by subtracting 4 from *ptr ?
i.e
(ptr)-4 = 9;
You can access the bytes that represent an object by converting a pointer to the object to a pointer to unsigned char and then accessing bytes through that pointer. For example, the fourth byte of i could be set to 9 by:
unsigned char *p = (unsigned char *) &i;
*(p+4) = 9;
However, you should not do this without good reason. It runs into portability problems and should only be done for special purposes and with careful attention to the C standard and/or the documentation of your C implementation. If you explain further why you want to do something like this, it might be possible to show better ways of doing it or to explain the hazards.
Note that the correct address for byte four (starting numbering at byte zero) is p+4, not p-4 as used in the question.
I would attempt something more readable
union {
long double d;
char v[sizeof(long double)];
} x;
x.d = 1234567890;
std::cout << x.d << ' ' << int(x.v[6]) << std::endl;
x.v[6] = 0xCC;
std::cout << x.d << ' ' << int(x.v[6]) << std::endl;
yields
1.23457e+09 44
1.23981e+09 -52
(*ptr)-4 = 9 is not permitted because it leads to RValue violation (Right hand side of an assignment operation cannot be another operation).
But you can use bit operations like:
(*ptr) = (*ptr) & 0x00009000;
First see here: How do you set only certain bits of a byte in C without affecting the rest?. The idea is to clear the byte you are interested in, and then set your value with an or operation. So in your case you'd do:
val &= ~0xff; // Clear lower byte
val |= 9 & 0xff; // Set Nine into the least significant byte.
I am adding values into the combo box as a string. Below is my code.
Platform Windows XP and I am using Microsoft Visual Studio 2003
language C++
error encountered -> "Run-Time Check Failure #2 - Stack around the variable 'buffer' was corrupted."
If I increase the size of the buffer to say 4 and above then I won't get this error.
My question is not related to how to fix that error, but I am wondering why I got this error if buffer size = 2.
According to my logic I have given buffer size = 2 as char[0] will store the valve of char[1] = null terminated character.
Now since char can store values from 0 to 255 , I thought this should be ok as my inserted values are from 1 to 63 and then from 183 to 200.
CComboBox m_select_combo;
const unsigned int max_num_of_values = 63;
m_select_combo.AddString( "ALL" );
for( unsigned int i = 1; i <= max_num_of_values ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
const unsigned int max_num_of_high_sats = 202 ;
for( unsigned int i = 183; i <= max_num_of_high_sats ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
Could you guys please give me an idea as to what I'm not understanding?
itoa() zero-terminates it's output, so when you call itoa(63, char[2], 10) it writes three characters 6, 3 and the terminating \0. But your buffer is only two characters long.
itoa() function is best avoided in favour of snprintf() or boost::lexical_cast<>().
You should read the documentation for itoa.
Consider the following loop:
for( unsigned int i = 183; i <= max_num_of_high_sats ; ++i )
{
char buffer[2];
std::string prn_select_c = itoa( i, buffer, 10 );
m_select_combo.AddString( prn_select_c.c_str() );
}
The first iteration converts the integer 183 to the 3 character string "183", plus a terminating null character. That's 4 bytes, which you are trying to cram into a two byte array. The docs tell you specifically to make sure your buffer is large enough to hold any value; in this case it should be at least the number of digits in max_num_of_high_sats long, plus one for the terminating null.
You might as well make it large enough to hold the maximum value you can store in an unsigned int, which would be 11 (eg. 10 digits for 4294967295 plus a terminating null).
the ito function is used to convert a int to a C sytle string based on the 3rd parameter base.
As a example, it just likes to print out the int 63 in printf. you need two ASII byte, one is used to storage CHAR 6, the other is used to storage CHAR 3. the 3rd should be NULL. So in your case the max int is three digital. you need 4 bytes in the string
You are converting an integer to ASCII, that is what itoa does. If you have a number like 183 that is four chars as a string, '1', '8', '3', '\0'.
Each character takes one byte, for example character '1' is the value 0x31 in ASCII.