I would like to copy a variable of 1 byte to relatively larger char array, and copy it back? How can I do that?
/* memcpy example */
#include <stdio.h>
#include <string.h>
struct Data {
unsigned char name[40];
int age;
};
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
int main ()
{
uint8_t myval = 8;
uint8_t myval_2 = 8;
Data mypass;
memcpy(&mypass.name, &myval, sizeof(uint8_t));
memcpy(&mypass.name+1, &myval_2, sizeof(uint8_t));
uint8_t* myvalnew = nullptr;
uint8_t* myvalnew_2 = nullptr;
memcpy(myvalnew, (uint8_t*)&mypass.name, sizeof(uint8_t));
memcpy(myvalnew_2, (uint8_t*)&mypass.name+1, sizeof(uint8_t));
return 0;
}
However I am getting errors.
&mypass.name creates a pointer to your name array, you want a pointer to the first element of your array, you can use either simply mypass.name or &mypass.name[0]. memcpy is unnecessary here as you can simply assign the elements:
mypass.name[0] = myval;
mypass.name[1] = myval_2;
Your second set of memcpys will fail as your myvalnew pointers are null, I'm not sure what you're trying to achieve here. If you're trying to get the values back you can again just use normal array access:
uint8_t myvalnew = mypass.name[0];
uint8_t myvalnew_2 = mypass.name[1];
Related
Below is a struct that I have and a variable of the type of this struct RtpHeader.
typedef struct _RTP_header
{
unsigned char csrc : 4;
unsigned char extension : 1;
unsigned char padding : 1;
unsigned char version : 2;
unsigned char payload : 7;
unsigned char marker : 1;
unsigned short seq;
unsigned int ts;
unsigned int ssrc;
} RtpHeader;
RtpHeader rtp_header;
rtp_header.version = 2;
rtp_header.payload = 96;
rtp_header.marker = 1;
rtp_header.seq = 0;
rtp_header.ts = htonl(std_random_device());
rtp_header.ssrc = htonl(std_random_device());
std::shared_ptr<char> buf;
// binary data is assigned to the buf variable here... (out of scope of this question.
memcpy(buf.get() + 4, &rtp_header, 12);
I do understand what the memcpy() fuction does. But I don't understand what + 4 does here.
The get() function of the std::shared_ptr returns the raw pointer to the data object that it shared.
In this case it will point to the raw char.
The +4 simply moves an additional 4 char sized memory positions.
If the shared object were to be a char[10] buffer, it would point at the 5th element in that array, buffer[4].
In your example there is no buffer, but a single char. In this case the result is undefined.
I have a std::string array which I need to convert to an unsigned char array so that I can use this array with third-party library which only accepts unsigned char array.
let say my array is
std::string array[3];
array[0] = "a105b";
array[1] = "c258e"
array[2] = "ff587";
I need to transfer this array into:
unsigned char cArray[3][5];
I can do hardwire the unsigned char as below:
unsigned char cArray[3][5] = {"a105b", "c258e", "ff587"};
but I was unable to find a way to do it using C++ code to transfer the data from the std::string array to the unsigned char array.
You could make a function that loops through the two arrays and copies from one to the other.
Example:
#include <algorithm>
#include <iostream>
#include <string>
template<size_t R, size_t N>
void foo(const std::string(&src)[R], unsigned char(&dest)[R][N]) {
// both `src` and `dest` must be arrays with `R` rows
// `N` is how many unsigned chars each inner array in `dest` has
for(size_t idx = 0; idx < R; ++idx) {
// Copy from `src[idx]` to `dest[idx]`
// Copy at most `N` chars but no more than the length of the string + 1
// for the null terminator:
std::copy_n(src[idx].c_str(), std::min(N, src[idx].size() + 1), dest[idx]);
// Add the below line if the arrays in cArray are supposed to
// be null terminated strings:
//dest[idx][N - 1] = '\0';
}
}
int main() {
std::string array[3];
array[0] = "a105b";
array[1] = "c258e";
array[2] = "ff587";
unsigned char cArray[3][5];
foo(array, cArray);
}
I can do hardwire the unsigned char as below
unsigned char cArray[3][5] = {"a105b", "c258e", "ff587"};
No, that's not valid in C++. You would have to make the inner array [6] in C++:
unsigned char cArray[3][6] = {"a105b", "c258e", "ff587"};
In code it could look like this:
#include <array>
#include <algorithm>
#include <cstring>
#include <string>
template<typename to_type, size_t buf_size, size_t number_of_strings>
void to_array(const std::array<std::string, number_of_strings>& input,
to_type (&output)[number_of_strings][buf_size])
{
for (std::size_t n = 0; n < number_of_strings; ++n)
{
const auto input_str = input[n].c_str();
// for input string include trailing 0 on input so add one to length
const auto copy_len = std::min(input[n].length()+1, buf_size);
std::memcpy(output[n], input_str, copy_len);
}
}
int main()
{
std::array<std::string, 3> input_array{ "a105b", "c258e", "ff587" };
unsigned char c_array[3][6];
to_array<unsigned char, 6>(input_array, c_array);
return 0;
}
It showed me again that 'c' style arrays are not nice to work with.
You can't return them from a function (like you can with std::array).
So you have to pass the output array as parameter to the conversion function too.
You are not permitted to assign to a plain array. You cannot define your own assignment operator for the plain array, because C++ does not allow overload of the assignment operator except as a non-static member function of a class.
One workaround may be to define an overload for a shift operator, and give a similar syntax to an input stream.
template <unsigned N>
void operator >> (std::string s, unsigned char (&a)[N]) {
auto n = (s.size() < N) ? s.size() + 1 : N;
std::copy_n(s.c_str(), n, a);
}
/*...*/
unsigned char cArray[3][5];
array[0] >> cArray[0];
array[1] >> cArray[1];
array[2] >> cArray[2];
I have this function that in the first call, is giving me back the Correct Encrypted Value
120692dbcdca656394fc10147e2418f2
But all that comes after are incorrect :
764e1a39b43c42f30da2e9e327d4ed22
b93b46dbc936ae3b06f571ffe1a59cac
b93b46dbc936ae3b06f571ffe1a59cac
a71787b35326e282f8c1bf3a0a034620
I'm new with C++ and I think it is a matter of initialization of one of the variables.
I did many Tests but I'm not able to point out where is the Error.
Could someone help me please ?
Thank You -
#include <openssl/aes.h>
#include <iostream>
#include <iomanip>
using namespace std;
char* pxEnAndDeCrypt(char* pStr )
{
static const unsigned char key[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
char *ptr = NULL;
unsigned char enc_out[80]= {};
unsigned char dec_out[80]= {};
int i,j,lenHexa ;
char enc_out_HEXA[200]= {};
unsigned char enc_out_TRANSF[200]= {};
unsigned char enc_out_BACK[200]= {};
AES_KEY enc_key, dec_key;
// ENCRYPT : Input =*pStr Output = enc_out
AES_set_encrypt_key(key, 128, &enc_key);
AES_encrypt((const unsigned char *)pStr, enc_out, &enc_key);
// TRANSFORM OUTPUT OF ENCRYPT TO HEXA : Input =enc_out Output = enc_out_HEXA
int len = strlen((char*)enc_out);
for (i = 0, j = 0; i < len; ++i, j += 2)
{
sprintf(enc_out_HEXA + j, "%02x", enc_out[i] & 0xff);
}
ptr = (char *) enc_out_HEXA;
// OUTPUT
return ptr;
}
The problem with your code is that your function returns a pointer to enc_out_HEXA.
ptr = (char *) enc_out_HEXA;
return ptr;
The issue here is that enc_out_HEXA is declared inside pxEnAndDeCrypt so it no longer exists once you have exitted pxEnAndDeCrypt, so your function is returning a pointer to an object which no longer exists. This results in the strange behaviour you see.
Since you are programming C++, the simple solution is to use C++ (your current code is pure C). Instead of returning a pointer, return a std::string.
#include <string>
std::string pxEnAndDeCrypt(char* pStr )
{
...
return ptr;
}
There are many other places in the above code where you could replace the C code with C++. But this simple change should be enough to get over the current problem.
Of course you will also have to change the code that calls pxEnAndDeCrypt, but since you didn't post that I can't really help with that.
EDIT
Here's an alternative solution that doesn't require std::string.
The basic problem is that enc_out_HEXA has been declared inside the pxEnAndDeCrypt function and so you can't use it (or a pointer to it) outside the function. So one solution is to move the enc_out_HEXA to the calling function and pass a pointer to that array to the function. Like this
void pxEnAndDeCrypt(char* pStr, char* result)
{
...
for (i = 0, j = 0; i < len; ++i, j += 2)
{
sprintf(result + j, "%02x", enc_out[i] & 0xff);
}
}
Then somewhere else in your code you will have
char enc_out_HEXA[200];
pxEnAndDeCrypt(some_string, enc_out_HEXA);
That's the solution that would be used in a C program.
How to store int values in *pData and display values from it?
int id = 12;
int age = 14;
unsigned char* pData = new unsigned char[8];
memcpy(pData,&id,4);/* using memcpy to copy */
pData = pData + 4;
memcpy(pData,&age,4);/* using memcpy to copy */
// How to print value from buffer *pData
After using memcpy to copy the bytes of an int into an unsigned char buffer, the only correct way to display the ints is to copy the bytes back into an int. For example:
int temp_int;
memcpy(&temp_int, pData, sizeof temp_int);
std::cout << temp_int << '\n';
memcpy(&temp_int, pData + sizeof temp_int, sizeof temp_int);
std::cout << temp_int << '\n';
Attempting to reinterpret the buffer as an int would cause undefined behaviour by violating the strict aliasing rule.
you can change pData into int *, then you can print the int valve.
cout<<*((int *)pData);
memcpy(pData,&id,4);
This line copies the four bytes data in id to pData as int but you declared it as char * .
if you declare it as int *pData = new int[2]; then you can ptint exact values.
using namespace std;
int id = 12;
int age = 14;
unsigned int* pData = new unsigned int[2];
memcpy(pData,&id,4);
pData = pData + 1;
memcpy(pData,&age,4);
pData = pData - 1;
cout<<"ID:"<<pData[0]<<"\nAge:"<<pData[1]<<endl;
This will print the values.
If you really need to allocate memory as unsigned char*, you can do it like below:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int id = 12;
int age = 14;
// const pointer to buffer which can contain 2 ints
unsigned char* const pData = new unsigned char[2*sizeof(int)];
// non-const pointer to operate on data
unsigned char* pDataPtr = pData;
memcpy(pDataPtr,&id,sizeof(int));
pDataPtr += sizeof(int);
memcpy(pDataPtr,&age,sizeof(int));
std::cout<<*reinterpret_cast<int*>(pData)<<std::endl;
std::cout<<*reinterpret_cast<int*>(pData + sizeof(int))<<std::endl;
delete [] pData;
return 0;
}
You can print pData using reinterpret_cast operator :
#include <iostream>
#include <cstring>
int main(void)
{
int id = 12;
int age = 14;
const size_t size = sizeof(int);
unsigned char* pData = new unsigned char[2*size];
memcpy(pData,&id,size);/* using memcpy to copy */
pData = pData + size;
memcpy(pData,&age,size);/* using memcpy to copy */
std::cout<<*reinterpret_cast<int*>(pData)<<std::endl;
pData = pData - size;
std::cout<<*reinterpret_cast<int*>(pData)<<std::endl;
delete []pData;
return 0;
}
I am trying to store two integer value into an char array in C++.
Here is the code..
char data[20];
*data = static_cast <char> (time_delay); //time_delay is of int type
*(data + sizeof(int)) = static_cast<char> (wakeup_code); //wakeup_code is of int type
Now on the other end of the program, I want to reverse this operation. That is, from this char array, I need to obtain the values of time_delay and wakeup_code.
How can I do that??
Thanks,
Nick
P.S: I know this is a stupid way to do this, but trust me its a constraint.
I think when you write static_cast<char>, that value is converted to a 1-byte char, so if it didn't fit in a char to begin with, you'll lose data.
What I'd do is use *((int*)(data+sizeof(int))) and *((int*)(data+sizeof(int))) for both reading and writing ints to the array.
*((int*)(data+sizeof(int))) = wakeup_code;
....
wakeup_code = *((int*)(data+sizeof(int)));
Alternatively, you might also write:
reinterpret_cast<int*>(data)[0]=time_delay;
reinterpret_cast<int*>(data)[1]=wakeup_code;
If you are working on a PC x86 architecture then there are no alignment problems (except for speed) and you can cast a char * to an int * to do the conversions:
char data[20];
*((int *)data) = first_int;
*((int *)(data+sizeof(int))) = second_int;
and the same syntax can be used for reading from data by just swapping sides of =.
Note however that this code is not portable because there are architectures where an unaligned operation may be not just slow but actually illegal (crash).
In those cases probably the nicest approach (that also gives you endianness control in case data is part of a communication protocol between different systems) is to build the integers explicitly in code one char at a time:
first_uint = ((unsigned char)data[0] |
((unsigned char)data[1] << 8) |
((unsigned char)data[2] << 16) |
((unsigned char)data[3] << 24));
data[4] = second_uint & 255;
data[5] = (second_uint >> 8) & 255;
data[6] = (second_uint >> 16) & 255;
data[7] = (second_uint >> 24) & 255;
I haven't tried it, but the following should work:
char data[20];
int value;
memcpy(&value,data,sizeof(int));
Try the following:
union IntsToChars {
struct {
int time_delay;
int wakeup_value;
} Integers;
char Chars[20];
};
extern char* somebuffer;
void foo()
{
IntsToChars n2c;
n2c.Integers.time_delay = 1;
n2c.Integers.wakeup_value = 2;
memcpy(somebuffer,n2c.Chars,sizeof(n2c)); //an example of using the char array containing the integer data
//...
}
Using such union should eliminate the alignment problem, unless the data is passed to a machine with different architecture.
#include <sstream>
#include <string>
int main ( int argc, char **argv) {
char ch[10];
int i = 1234;
std::ostringstream oss;
oss << i;
strcpy(ch, oss.str().c_str());
int j = atoi(ch);
}