uint8_t element assignment to uint8_t array in C++ - c++

I am trying to create a uint8_t array and try to change the first element of the array, then print it to the terminal as a string.
But, after I assign currBlock (changed block) to arr[0], cout gives an error. I tried to find the answer in StackOverflow but couldn't find a similar question. Can you help me with it?
Error: bitset::_M_copy_from_ptr
#include <iostream>
#include <sstream>
#include <bitset>
int main()
{
uint8_t arr[3]{0};
uint8_t currBlock{arr[0]};
int flag{1};
currBlock ^= (-flag ^ arr[0]) & (1UL << 3);
cout << "Buffer is : " << bitset<24>(arr).to_string() << endl;
arr[0] = currBlock;
cout << "Buffer is : " << bitset<24>(arr).to_string() << endl;
return 0;
}
I was expecting a print out of the uint8_t, but instead I get an error.

Related

Why does Visual Studio output this in my C++ program (adding string and character)? [duplicate]

The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.
In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}
Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo

What's the behaviour of "" + number and why it compile?

The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.
In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}
Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo

How to store randomly generated unsigned int numbers in a bitset

I have a bitset in which I need to store a # of randomly generated integers (store its bit representation of course). So, the thing is that I am confuse on how to do that.
i.e suppose that I generate the integers (all unsigned int) 8, 15 , 20, one at a time. How can I store the recently generated integer in my existing bit set.
Say that I start by generating "8" and store in the bitset, then I generate "15" and store it in the bitset.
I don't know or don't understand how to store those values within the bitset.
Note: I know in advance the size of the bitset, the size is based on the number of integers that I am going to generate, and that I know too. So, at the end what I need is a bitset with all the bits set matching the bits of all the generated integers.
I'll Appreciate your help.
How can I store the recently generated integer in my existing bit set.
You can generate a temporary bitset form the integer and then assign values between the two bitsets.
Example program:
#include <iostream>
#include <bitset>
#include <cstdlib>
int main()
{
const int size = sizeof(int)*8;
std::bitset<2*size> res;
std::bitset<size> res1(rand());
std::bitset<size> res2(rand());
for ( size_t i = 0; i < size; ++i )
{
res[i] = res1[i];
res[size+i] = res2[i];
}
std::cout << "res1: " << res1 << std::endl;
std::cout << "res2: " << res2 << std::endl;
std::cout << "res: " << res << std::endl;
return 0;
}
Output:
res1: 01101011100010110100010101100111
res2: 00110010011110110010001111000110
res: 0011001001111011001000111100011001101011100010110100010101100111
Update
A function to set the bitset values given an integer can be used to avoid the cost of creating temporary bitsets.
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <climits>
const int size = sizeof(int)*8;
void setBitsetValue(std::bitset<2*size>& res,
int num,
size_t bitsetIndex,
size_t numIndex)
{
if ( numIndex < size )
{
res[bitsetIndex] = (num >> numIndex) & 0x1;
setBitsetValue(res, num, bitsetIndex+1, numIndex+1);
}
}
int main()
{
std::bitset<2*size> res;
int num1 = rand()%INT_MAX;
int num2 = rand()%INT_MAX;
std::bitset<size> res1(num1);
std::bitset<size> res2(num2);
std::cout << "res1: " << res1 << std::endl;
std::cout << "res2: " << res2 << std::endl;
setBitsetValue(res, num1, 0, 0);
setBitsetValue(res, num2, size, 0);
std::cout << "res: " << res << std::endl;
return 0;
}

Right Shift in C++ giving unusual results (unsigned 64-bit)

I am in the horrible world of bit shifting. I have the following code:
I am shifting this number: 140638023551944 >> 5.
The binary representation for 140638023551944 according to http://www.binaryhexconverter.com/decimal-to-binary-converter is
1000011000011111011101000111
Right shifted 5, I expect: 0000010000110000111110111010
But instead, I get 4394938235998, which is 111111111101000110101110110111110001011110.
That number, to me, looks to have almost nothing at all to do with the original number. I don't see a pattern in one that exists in the other. It is very bizarre.
The code is along the lines of:
uint64_t n, index, tag;
uint64_t one = 1;
uint64_t address = 140638023551944;
/*left shift to get index into the last index.length() number of slots*/
cout << "original address is " << address << " " << "\n";
n = (address >> 5);
cout << "after right shifting away offset bits " << n << "\n";
"address" is populated with the correct integer, 140638023551944. I have verified that.
What is this bizarre behavior? It is consistent with this simulator: http://www.miniwebtool.com/bitwise-calculator/bit-shift/?data_type=10&number=140638023551944&place=5&operator=Shift+Right! But I am pretty sure right shift is not supposed to work that way!
// EVERYTHING WORKS CORRECTLY!
#include <cassert> // assert()
#include <iostream> // cout
#include <cstdint> // UINT64_MAX
using namespace std;
int main() {
uint64_t n, index, tag;
uint64_t one = 1;
uint64_t address = 140638023551944;
/*left shift to get index into the last index.length() number of slots*/
cout << "original address is " << address << " " << "\n";
n = (address >> 5);
cout << "after right shifting away offset bits " << n << "\n";
{ // Everything works correctly!
assert( 140638023551944>>5 == 140638023551944/32 );
assert( 140638023551944>>5 == 4394938235998 );
assert( 140638023551944/32 == 4394938235998 );
assert( 140638023551944 < UINT64_MAX );
}
}

Increment IP address

In that program I want to increment IP address. And I see output like that:
125.23.45.67
126.23.45.67
127.23.45.67
128.23.45.67
129.23.45.67
130.23.45.67
131.23.45.67
132.23.45.67
133.23.45.67
134.23.45.67
But I want to see output like this:
124.23.45.67
124.23.45.68
124.23.45.68
124.23.45.70
124.23.45.71
124.23.45.72
124.23.45.73
124.23.45.74
124.23.45.75
124.23.45.76
Here is program code:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#include "winsock2.h"
#pragma comment(lib,"wsock32.lib")
void main()
{
in_addr adr1;
in_addr adr2;
int i;
adr1.s_addr=inet_addr("124.23.45.67");
adr2.s_addr=inet_addr("as.34.34.56");
if (adr1.s_addr!=INADDR_NONE)
cout << " adr1 correct" << endl;
else
cout << " adr1 incorect " << endl;
if (adr2.s_addr!=INADDR_NONE)
cout << " adr2 correct" << endl;
else
cout << " adr2 incorect" << endl;
cout << inet_ntoa(adr1) << endl;
cout << inet_ntoa(adr2) << endl;
for (i=0;i<10;i++)
{
adr1.s_addr ++;
cout << inet_ntoa(adr1) << endl;
}
}
Big endian and little endian gets another one! Use htonl and ntohl to convert back and forth.
for (i=0;i<10;i++)
{
adr1.s_addr = htonl(ntohl(adr1.s_addr) + 1);
cout << inet_ntoa(adr1) << endl;
}
To increment an IP address you will need to break up the in_addr object into 4 int objects (a short int will also do) and increment the 4th one until it hits 256, and then reset it to 1 and increment the 3rd one, etc. You shouldn't be using ++ on the in_addr object directly.
EDIT: Okay, so you can properly increment it if you reverse the byte order. I personally wouldn't do it that way. Especially if all you're doing is outputting IP strings and not using them as an in_addr elsewhere in code.
Instead of using adr1.s_addr:
adr1.s_addr=inet_addr("124.23.45.67");
adr2.s_addr=inet_addr("as.34.34.56");
Use this:
u_long addr1=inet_addr("124.23.45.67");
And increment addr1, i.e. addr1++
the last octet gets incremented.
Or follow this formula:
if IP is A.B.C.D then u_long addr = A + 256*B + 256*256*C + 256*256*256*D