I have two vectors.
One is
std::vector<unsigned char> one_v;
and the other is
std::vector<bool> outputValuesInBits;
I pushed values to both one_v and outputValuesInBits.
Both vectors have two bytes.
one_v[0] and [1] are filled with data which would be 2 bytes.
outputValuesInBits[0] to [15] are filled with data which would be 2 bytes.
Now, I would like to copy(memcpy) data to char array.
I can successfully copy data from one_v vector as following.
unsigned char* output = new unsigned char[one_v.size()]();
memcpy(&output, one_v.data(), 2);
But I cannot copy data from outputValuesInBits.
If I do as follow,
unsigned char* output = new unsigned char[outputValuesInBits.size()/8+1]();
memcpy(&output, outputValuesInBits.data(), 2);
It gives me an error
error: invalid use of void expression
memcpy(&output, outputValuesInBits.data(), 2);
Can anyone please tell me how I can copy the bool vector to char array?
Thank you in advance!
I'm afraid you cannot in a portable way. Cplusplus page on vector says: The specialization has the same member functions as the unspecialized vector, except data, emplace, and emplace_back, that are not present in this specialization. That means that data in not defined what explains the error when you try to use it.
If portability is not an option, there will be no solution because The storage is not necessarily an array of bool values, but the library implementation may optimize storage so that each value is stored in a single bit. (emphasize mine). My understanding of the may is that you cannot even be sure that the 16 boolean are stored in 2 consecutive bytes: the implementation must only provide you a way to use them (almost) as if they were stored in 16 different booleans.
If you can forget partability, you will have to find the source for you current implementation to know where and how the byte array is stored... but it is not that easy...
std::vector<bool> doesn't have a data member function
At least in g++ compiler you can use the _M_p member of the vector::iterator, which is the pointer to the data.
Example:
std::vector<bool> vBool(16, false);
vBool[0] = true;
vBool[2] = true;
vBool[13] = true;
std::vector<unsigned char> vChar(2);
unsigned short *ptrUS = reinterpret_cast<unsigned short *>( &(vChar[0]) );
*ptrUS = *reinterpret_cast<unsigned short *>(vBool.begin()._M_p);
std::cout << (unsigned int)vChar[0] << " " << (unsigned int)vChar[1] << "\n";
gives in output '5 32', which corresponds to the numbers with 1st and 3rd bit (5) and with the 6th bit (32).
Related
I want to calculate a hash of the structure passing as string. Although vlanId values are different, the hash value is still the same. The StringHash() funtion calculates the values of the hash. I haven't assigned any value to portId and vsi.
#include<stdio.h>
#include <functional>
#include <cstring>
using namespace std;
unsigned long StringHash(unsigned char *Arr)
{
hash<string> str_hash;
string Str((const char *)Arr);
unsigned long str_hash_value = str_hash(Str);
printf("Hash=%lu\n", str_hash_value);
return str_hash_value;
}
typedef struct
{
unsigned char portId;
unsigned short vlanId;
unsigned short vsi;
}VlanConfig;
int main()
{
VlanConfig v1;
memset(&v1,0,sizeof(VlanConfig));
unsigned char *index = (unsigned char *)&v1 + sizeof(unsigned char);
v1.vlanId = 10;
StringHash(index);
StringHash((unsigned char *)&v1);
v1.vlanId = 12;
StringHash(index);
StringHash((unsigned char *)&v1);
return 0;
}
Output:
Hash=6142509188972423790
Hash=6142509188972423790
Hash=6142509188972423790
Hash=6142509188972423790
You pass the bytes of your structure to a function expecting a zero terminated string. Well, the first byte of your structure already is zero, so you calculate the same hash every time.
Now, that is the explanation why, but not the solution to your problem. Passing a random sequence of bytes to a function expecting a zero-terminated sequence of characters is going to fail spectacularly, no matter how you do it.
Find another way to hash your structure. You are already using hash<>, why not use it for your case:
namespace std
{
template<> struct hash<VlanConfig>
{
std::size_t operator()(VlanConfig const& c) const noexcept
{
std::size_t h1 = std::hash<char>{}(c.portId);
std::size_t h2 = std::hash<short>{}(c.vlanId);
std::size_t h3 = std::hash<short>{}(c.vsi);
return h1 ^ (h2 << 1) ^ (h3 << 2); // or use boost::hash_combine
}
};
}
Then you can do this:
VlanConfig myVariable;
// fill myVariable
std::cout << std::hash<VlanConfig>{}(myVariable) << std::endl;
I can't say for certain, but most likely your issue is structure padding. Unless explicietly set ot pack members and ignore alignment, most compilers will set up the struct as follows:
Byte 0: portId
Byte 1: padding
Bytes 2,3: vlanId
Bytes 4,5: vsi
So when you figure the address of index, it'll point to the padding byte, which is always zero. Thus you're always hashing an empty string.
You should be able to check this in a debugger by inspecting index and comparing it to the address of vlanId.
-- Edit --
After giving this some more thought, I have to say that in my extremely humble opinion, this isn't a good way to get a hash value. Trying to treat several numeric values that might, or might not, be contiguous in memory as a std::string, has too many possibilities for error.
Start with the fact that even if you do get the address correct, consider what happens when you hash two different configurations, one of which has vlanId set to 256, while the other has it set to 512. Assuming a little endian machine, both of those will have a zero byte as the first character of the string, and so you're right back here again.
Worse yet is the case when all four bytes in vlanId and vsi are non zero. In that case, you'll read right off the end of your struct, and keep on going, reading who knows what. There's no way that's going to end well.
One possible solution is to figure the size of data, and use the following ctor for std::string: string (char const *s, size_t n); which has the advantage of forcing the string to exactly the size you want.
I want to convert size_t to vector of unsigned chars. This vector is defined as 4 bytes.
Could anybody suggest a suitable way to do that?
Once you've reconciled yourself to the fact that your std::vector is probably going to have to be bigger than that - it will need to have sizeof(size_t) elements - one well-defined way is to access the data buffer of such an appropriately sized vector and use ::memcpy:
size_t bar = 0; /*initialise this else the copy code behaviour is undefined*/
std::vector<uint8_t> foo(sizeof(bar)); /*space must be allocated at this point*/
::memcpy(foo.data(), &bar, sizeof(bar));
There is an overload of data() that returns a non-const pointer to the data buffer. I'm exploiting this here. Accessing the data buffer in this way is unusual but other tricks (using unions etc.) often lead to code whose behaviour is, in general, undefined.
By "convert", I'll assume you mean "copy", since vector will allocate and own its memory. You can't just give it a pointer and expect to use your own memory.
An efficient way to do so which avoids two-stage construction (that causes initialization of the array with zero) is to do this:
auto ptr = reinterpret_cast<uint8_t*>(&the_size);
vector<uint8_t> vec{ptr, ptr + sizeof(size_t)};
Note that sizeof(size_t) is not required to be 4. So you shouldn't write your code assuming that it is.
You could write a generic converter using std::bitset
template <typename T>
std::vector<unsigned char> Type_To_Bit_Vector(T type, char true_char, char false_char){
//convert type to bitset
std::bitset<sizeof(type)*8> bset(type);
//convert bitset to vector<unsigned char>
std::vector<char> vec;
for(int i = 0 ; i < bset.size() ; i++){
if (bset[i]){
vec.push_back(true_char);
}else{
vec.push_back(false_char);
}
}
return vec;
}
You could then get a desired vector representation like so:
auto vec = Type_To_Bit_Vector(size_t(123),'1','0');
I have following in my code:
static unsigned char* table;
...
table = something here;
Now I have to assign this table to variable of type std::vector<unsigned char> and I am unable to do so. I am doing:
unsigned char* buffer = (unsigned char*) table;
std::vector<unsigned char>::size_type size = strlen((const char*)buffer);
std::vector<unsigned char>static rawTable(buffer, buffer + size);
for(ByteBuffer::iterator it=rawTable.begin();it!=rawTable.end();++it)
std::cout << "Raw Table: "<<*it<< std::endl;
I am able to compile the code, but no value is there inside rawTable. Please help!
I have verified that variable table has value. I appreciate any help on this. Thanks.
strlen gives you the length of a string, not the size of an arbitrary memory region. If your table has a '\0' anywhere inside, strlen will find it and stop counting.
Also, by making rawTable a static variable, it will not update its value if buffer or size ever change. static variables are constructed only once.
Also, if this is supposed to be a table of numeric data, you should cast to a numeric non-character type. Otherwise cout may interpret it as ASCII codes.
You have a pointer of type unsigned char* pointing to an array.
Then you want to push every element of the array into a std::vector<unsigned char>, right?
If so, the key is to know the size of the array. You need to know the size beforehand. There's no way to determine the size of the array in the general case with some keyword or function if all that is visible to you is a pointer of type unsigned char*. You need to pass that information along with the pointer somehow.
In the case when the pointer of type unsigned char* points to an array of characters which is null-terminated (e.g. {'f', 'o', 'o', '\0'}), then you can use the C-string function strlen to count the number of characters in the array using only the pointer. However if the array is not null-terminated this will result in undefined behaviour.
When you have the size it's a simple matter to populate the std::vector with the arrays elements:
std::vector<unsigned char> v(arr, arr + size); // arr = pointer to array.
This is why you should use the containers in the standard library instead of raw arrays, as these containers internally keep track of the size and you can always access it with the size() function.
For constant size arrays use std::array. Example:
std::array<unsigned char, 3> arr{'f', 'o', 'o'}; // arr.size() == 3
// Print its contents.
for (auto c : arr) {
std::cout << c << std::endl;
}
How would I get the size of this:
char* stringit[4] = {"H","H","UH","i"};
I tried:
sizeof(stringit);
and it outputed 32.
I tried to make a for loop:
for (i= 0; check != 0; ++i){
check = stringit[i];
}
and that did not work either. Is there anyway to do this without having to pass in the size of the array?
make it a NULL terminated array of pointers
char* stringit[] = {"H","H","UH","i" , NULL };
Then just count the pointers until you find a null pointer.
The right way to get the number of elements of an array is to divide its actual size (in bytes) by the size of an element:
sizeof(stringit) / sizeof(stringit[0])
But unless you have extremely specific requirements, you should use a standard container like vector (and string too instead of char* C strings):
std::vector<std::string> stringit = {"H","H","UH","i"};
std::cout << stringit.size();
As #KonradRudolph mentioned, vector is nice if your number of elements is variable. If the number of elements is known at compile time and will never change you could instead use array:
std::array<std::string, 4> stringit = {"H","H","UH","i"};
std::cout << stringit.size();
As long as you have access to the array itself, i.e. as long as you have not converted it to a pointer, the number of elements can be calculated as
sizeof stringit / sizeof *stringit
which will evaluate to a compile-time constant 4 in your case.
Whether this is what you are looking for or not depends on some additional details, which you did not provide in your question. You mention "having to pass in the size of the array". Pass where?
32 is the right size. The variable stringit is an array of 4 char pointers, and each pointer is 8 bytes.
What is it that you are trying to do?
char* stringit[4] = {"H","H","UH","i"};
is an array of 4 strings, i.e. array of 4 char* (pointer holds an address, 64bit address = 8 bytes). That's why you get 32. To retrieve the number of elements, you could do:
int count = sizeof(stringit) / sizeof(stringit[0]);
which will give you 4. But note that this kind of approach isn't much flexible and I'd rather use some STL container, i.e. std::vector<char*> or yet even better, get rid of C-style strings as well and use std::vector<std::string> instead.
The sizeof works for static arrays. It's giving you the size of the construct in bytes.
If you want length, do sizeof(stringit) / sizeof(char*).
For a more flexible solution that is probably the ``Right way" to do things in C++ (which works for dynamic arrays), just use std::array, or std::vector/std::list, if you need more dynamic allocation.
http://www.cplusplus.com/reference/array/array/
http://www.cplusplus.com/reference/vector/vector/
http://www.cplusplus.com/reference/list/list/
With this construct, you can simply use a size() member.
Remember to pass by reference when necessary to avoid needless copying.
I'm reading multiple reports from a HID device into an unsigned char, then trying to copy the data to a std::vector. I'm also writing the data out to a file for hex analysis, whose content appears to be correct when I view it. However, the std::vector doesn't appear to contain the correct data when I dump it to the console.
This is the code:
typedef vector<unsigned char> buffer_t;
buffer_t sendCommand (hid_device *devh, const unsigned char cmd[], int reports) {
unsigned char outbuf[0x40];
buffer_t retbuf(0x40 * reports);
hid_write(devh, cmd, 0x41);
int i;
FILE *file = fopen("test.out", "w+b");
while (i++ < reports) {
hid_read(devh, outbuf, 0x40);
fwrite(outbuf, 1, sizeof(outbuf), file);
retbuf.push_back(*outbuf);
}
fclose(file);
cout << &retbuf[0];
return retbuf;
}
I have a feeling I'm way off the mark here; I'm fairly new to C/C++, and I've been stuck with this for a while now. Can anyone tell me what I'm doing wrong, or point me in a better direction?
You want to add multiple unsigned char objects to your vector, but push_back only adds one.
So, replace retbuf.push_back(*outbuf); with either:
for (size_t i = 0; i < sizeof(outbuf); ++i) {
retbuf.push_back(outbuf[i]);
}
or
std::copy(outbuf, outbuf+sizeof(outbuf), std::back_inserter(retbuf));
or
retbuf.insert(retbuf.end(), outbuf, outbuf+sizeof(outbuf));
which all do the same thing.
You create your vector with a certain size:
buffer_t retbuf(0x40 * reports);
but push_back increases the size of the vector by adding an element at the end. You should create it empty:
buffer_t retbuf;
Optionally, you could arrange for the vector to have enough space allocated, ready for the elements you're going to add:
retbuf.reserve(0x40 * reports);
This is purely a performance issue, but sometimes it's a significant issue for large vectors, or vectors of types that (unlike unsigned char) are expensive to copy/move when the vector runs out of internal space and has to allocate more.
A note on style: you repeat the literal value 0x40 a few times, and also use sizeof(outbuf). It's often best to define a constant, and use the name throughout:
const int report_size = 0x40;
This is partly in case the number changes in future, but also it's about the readability of your code -- if someone sees 0x40 they may or may not immediately understand why that is the correct value. If someone sees report_size then they don't know what value that actually is until they look it up, but they do know why you're using that value.
The problem is in this line: buffer_t retbuf(0x40 * reports); It means that you create vector with 0x40 * reports elements filled with default value for unsigned char (zero). Then push_back() just adds new elements to the end of vector and doesn't affect existing elements.
You need to rewrite it this way:
buffer_t retbuf; // Empty vector
retbuf.reserve(0x40 * reports); // Preallocate memory for known element count
This way push_back() will work as expected and add elements to empty vector from beginning.
And of course you shall push_back() all elements of outbuf, not only first one (*outbuf).
To push back multiple values use std::vector's function assign. For example:
std::vector<char>vec1;
char array[3] = {'a', 'b', 'c'};
vec1.assign(array, array+3);
I am currently working on a project were I had to do this.
Your vector is of a type unsigned char, which means every element of it is of this type. Your outbuf is an array of unsigned chars.
The push_back() only appends one item to the end of the vector, so push_back(*outbuf) will only add the first element of the outbuf to the vector, not all of them.
To put all the data into the vector, you will need to push_back them one-by-one, or use std::copy.
Note that since outbuf is a char array, then *outbuf will be the first element of the char array because of the array/pointer duality.
I think you probably wanted to do:
typedef vector<string> buffer_t; // alternatively vector<unsigned char*>
...
retbuf.push_back(outbuf);
...
Or
typedef vector<unsigned char> buffer_t;
...
for (size_t i = 0; i < sizeof(outbuf); i++)
retbuf.push_back(outbuf);
...