I want to know how can I combine several byte arrays into 1?
I have this:
byte MessageStart [] = {0x02};
byte Next [] = {0x5C , 0x73};
byte messgae[] = {0x30 , 0x35};
byte BeforeEnd [] = {0x5C , 0x3B};
byte MessageEnd [] = {0x03};
I want to have one byte array with all of them, the final result needs to be:
byte Final [] = {0x02, 0x5C, 0x73, 0x30, 0x35, 0x5C, 0x3B, 0x03}
How do I do this?
Maybe something like this:
byte *concatbytes(const byte *source, byte *destination, int length)
{
for (int i = 0; i < length; i++)
{
*destination++ = *source++;
}
return destination;
}
...
byte MessageStart[] = { 0x02 };
byte Next[] = { 0x5C , 0x73 };
byte messgae[] = { 0x30 , 0x35 };
byte BeforeEnd[] = { 0x5C , 0x3B };
byte MessageEnd[] = { 0x03 };
byte Final[8]; // 8 is the hardcoded length of sum of all 5 arrays
byte *dest = Final;
dest = concatbytes(dest, MessageStart, sizeof(MessageStart));
dest = concatbytes(dest, Next, sizeof(Next));
dest = concatbytes(dest, messgae, sizeof(messgae));
dest = concatbytes(dest, BeforeEnd, sizeof(BeforeEnd));
dest = concatbytes(dest, MessageEnd, sizeof(Next));
The Final array may be obtained differently, for example by dynamic memory allocation. This is left as an exercise for the reader.
Here, I am passing an array of bits to some other function.
Since, array size is too large, it throws an error saying "data segment too large" while compiling.
I have newly edited the code. But, the error: data segment too large still exists
This is the code:
char TxBits[]={0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,1,0,1,1,0,1,1,1,0,
0,0,0,1,1,0,0,0,1,0,0,1,0,0,1,1,1,1,1,1,0,1,0,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int nTxBits = sizeof(TxBits)/sizeof(char);
void data(char *TxBits,int nTxBits, int loopcount)
{
int i;
for (i = 0;i < nTxBits;i++)
{
gpio=TxBits[i];
wait(loopcount);
}
}
So, I am thinking of converting bits in an array to bytes and passing to function. May I know how to proceed? open to suggestions.
Kindly reply
From your code I reckon you're working with some micro-controller so I'm not sure if you're serious about the C++ tag or not. If you are, this is a C++-style solution which uses std::bitset (specialised container for dealing with bits which will require less space):
std::bitset<134> foo (std::string("01010101010101010101010100101010101010101010101010010101010101010101010101001010101010101010101010100101010101010101010101010100000000"));
void data(const std::bitset& bitset, int loopcount) {
// if C++11
for (auto& bit : foo) {
gpio = bit;
wait(loopcount);
}
// if C++98
// for (int i = 0; i<bitset.size(); i++) {
// gpio = foo[i];
// wait(loopcount);
// }
}
You probably need this:
void data(char *TxBits, int size) // size of the number of elements of your table
{
int i;
for (i = 0;i < size; i++)
{
gpio=TxBits[i];
wait(loopcount);
}
}
Calling the function
data(TxBits, sizeof(TxBits) / sizeof(TxBits[0]);
To get the number of elements of an array we use sizeof(TxBits) / sizeof(TxBits[0] where sizeof(TxBits) is the number of bytes the array takes in memory and sizeof(TxBits[0] is the size of one element of the array.
I am passing an array of bits to some other function
No, you are passing an array of bytes, each byte having the binary value 00000000 or 00000001.
In order to save memory, you should store bit values as actual bits and not as bytes:
uint8_t TxBits[]=
{ 0x55, // 0,1,0,1,0,1,0,1,
0x55, // 0,1,0,1,0,1,0,1,
0x55, // 0,1,0,1,0,1,0,1,
0x00, // 0,0,0,0,0,0,0,0,
0x20, // 0,0,1,0,0,0,0,0,
...
};
size_t nTxBits = sizeof(TxBits) / 8;
You should also avoid the char type whenever doing arithmetic, since it has implementation-defined signedness.
Also if this is a small microcontroller system, you should allocate the data in ROM instead of RAM whenever possible. That is: const uint8_t TxBits[].
Your Parameter is not declared correctly. Replace this:
void data(char TxBits)
by this
void data(char [] TxBits)
Your function
void data(char TxBits)
Should be
void data(char *TxBits, size_t nTxBits)
{
int i;
for (i = 0;i < nTxBits;i++)
{
gpio=TxBits[i];
wait(loopcount);
}
}
You can call it by:
data ( TxBits, sizeof(TxBits)/sizeof(TxBits[0]) );
In this specific case, you have a char array, and you can also write:
data (TxBits, sizeof(TxBits));
I have an issue with C++ and creating a reference byte[].
In C# my method is:
public static void SetBitAt(ref byte[] Buffer, int Pos, int Bit, bool Value)
{
byte[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
if (Bit < 0) Bit = 0;
if (Bit > 7) Bit = 7;
if (Value)
Buffer[Pos] = (byte)(Buffer[Pos] | Mask[Bit]);
else
Buffer[Pos] = (byte)(Buffer[Pos] & ~Mask[Bit]);
}
I want to translate it to C++, but I can't get the refworking for C++. I saw something about the & symbol and I tried something like this:
void SetBitAt(byte& buffer[], int Pos, int Bit, bool Value)
{
byte Mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
if (Bit < 0) Bit = 0;
if (Bit > 7) Bit = 7;
if (Value)
{
buffer[Pos] = (byte)(buffer[Pos] | Mask[Bit]);
}
else
{
buffer[Pos] = (byte)(buffer[Pos] & ~Mask[Bit]);
}
}
but then I get the Error:
'buffer': arrays of references are illegal.
So how can I change my C++ code to work with a reference array?
EDIT:
I use this method for setting a buffer, but it doesn't change when I use this method.
other class:
buffer = ReadDB(2); //Read the values in the DataBlock
SetBitAt(buffer, 0,0 true); //Set bit 0,0 to 1(true)
WriteDB(2, buffer); //Write the values to the Datablock
but the buffer doesn't change. its the same value.
If you want to pass array by reference, you should
void SetBitAt(byte (buffer&)[10], int Pos, int Bit, bool Value)
But in your case, you don't need that, just
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value)
Note in this case array will decay to pointer (i.e. byte*), that means the size of array won't be reserved as pass by reference would.
'buffer': arrays of references are illegal.
This is due to operator precedence. Saying byte &buffer[] is an array of references, while saying byte (&buffer)[size] is a reference to an array.
See C++ pass an array by reference for more details.
So how can I change my C++ code to work with a reference array?
When passing your array as a function argument, you should drop & symbol. You can still modify the contents of your array because the array's address is passed instead.
Assuming you have a typedef of char to byte, your function signature should look like this:
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value) { ... }
Note that the above is equivalent to passing a pointer:
void SetBitAt(byte *buffer, int Pos, int Bit, bool Value) { ... }
Modifying the contents of your array is still a matter of saying buffer[Pos] = // some value;
This post on What is array decaying? should be useful.
Shouldn't it simply be like this:
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value)
{
byte Mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
if (Bit < 0) Bit = 0;
if (Bit > 7) Bit = 7;
if (Value)
{
buffer[Pos] = (byte)(buffer[Pos] | Mask[Bit]);
}
else
{
buffer[Pos] = (byte)(buffer[Pos] & ~Mask[Bit]);
}
}
In this way, buffer is passed as a pointer, and buffer[Pos] references to the Pos-th element of buffer. It is plain C, but it should work.
You can pass it simply by address as:
void SetBitAt(byte* buffer, int Pos, int Bit, bool Value) { ... }
or simply as:
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value) { ... }
Either one will tell the compiler that byte pointer is passed to function, althrough with second header you omit pointer arithmetics ;)
First timer with allocator.
I am really struggling with a custom allocator.
I would say its obvious I don't know what I'm doing here.
My goal is to put all of the memory for the object in the process's heap.
I want the allocation to come from the system so its not language / runtime dependent.
I don't really want a struct, I just want:
std::list< WCHAR[SIZE], TestAllocator<WCHAR[SIZE]>> list;
or, I'd allocate the memory outside of the list and then just store a pointer to it
std::list< void*, TestAllocator<void*>> list;
But I don't see how to do it with non struct / classes. So I have a struct.
This thing crashes all over the place.
The code below that instantiates the list crashes, it doesn't even have to get to a list item creation / insert.
The allocator is used for the list creation before I attempt to add an item. (which I don't understand.) It seems to me that the allocator should only be used for the struct type I'm trying to add to the list. If the allocator is used to create the list and the items it holds how do I create the memory for the 2 different types, the list type and the list entry type?
Some other observations / questions.
When my list is created, it is placed at the memory address created:
OSAllocator::allocate count:[1] bytes each:[8][0x8] bytes total:[8][0x8]addr:[4305640][0x41B2E8]
OSAllocator::construct placement new:[4305640][0x41B2E8] sizeof(val):[8][0x8]
However, when my entry is created, it is placed 2 bytes past the address created:
OSAllocator::allocate count:[1] bytes each:[8200][0x2008] bytes total:[8200][0x2008] addr:[8837144][0x86D818]
OSAllocator::construct placement new:[8837152][0x86D820] sizeof(val):[8192][0x2000]
Is there an explanation for that?
Please help point out what I'm missing.
Thanks.
// allocator...
pointer allocate(size_type size, TestAllocator<void>::const_pointer hint = 0)
{
pointer p = (pointer)::HeapAlloc( ::GetProcessHeap(),
HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE,
size*sizeof(T) );
gCountAllocate++;
if( OSAllocatorConsole )
wprintf( L"OSAllocator::allocate: [%u][0x%X]\n", p, p );
return p;
}
size_type max_size() const throw() {return size_t(-1) / sizeof(value_type);}
void construct(pointer p, const T& val)
{
gCountConstructPlaceNew++;
if( OSAllocatorConsole )
wprintf( L"OSAllocator::construct placement new:[%u][0x%X]\n", p, p );
::CopyMemory( p, &val, sizeof(val) );
}
typedef struct _LogLine
{
WCHAR _logLine[4*1024];
} LOGLINE, *PLOGLINE;
DWORD TestAllocatorChar(int argc, WCHAR* argv[])
{
WCHAR buf[32] = {0};
DWORD total = 1;
std::list< LOGLINE, TestAllocator<LOGLINE>> list;
PLOGLINE pll = NULL;
LOGLINE ll = {0};
for(int i=0; i<total; i++ )
{
::StringCchPrintfW( ll._logLine, 4*1024, L"count:[%u]", i );
list.push_back( ll );
}
for( int i=0; i<total; i++ )
{
//pll = list.front();
wprintf( L"%s\n", list.front()._logLine );
wprintf( L"HeapFree item:[%u]\n", i );
//::HeapFree( ::GetProcessHeap(), HEAP_NO_SERIALIZE, p );
list.pop_front();
}
return 0;
}
void Example1( char* ArrayA, unsigned int Length )
{
if( ArrayA == 0 )
{
ArrayA = new char[ Length + 1 ];
// Fill it with 2 - whatever
::memset( ArrayA, 0x02, sizeof( char ) * Length );
ArrayA[ Length ] = '0\n';
}
// Do whatever with ArrayA
// Clean-Up
// Error occurs
delete [ ] ArrayA;
};
void Example2( char* ArrayB, unsigned int Length )
{
bool IsDynamic = false;
if( ArrayB == 0 )
{
ArrayB = new char[ Length + 1 ];
// Fill it with 2 - whatever
::memset( ArrayB, 0x02, sizeof( char ) * Length );
ArrayB[ Length ] = '0\n';
IsDynamic = true;
}
// Do whatever with ArrayA
// Clean-Up
// Have to check...
if( IsDynamic )
delete [ ] ArrayB;
};
int main( void )
{
Example1( "\x01\x02\0x03", 3 ); // Example1 WILL NOT* declare ArrayA as a dynamic array - ERROR (caused by deleting non dynamic array)
Example2( 0, 3 ); // ArrayB will be a dynamic array - OK
Example1( 0, 3 ); // OK
Example2( "\x04\x05\0x06", 3 ); // ArrayB isn't a dynamic array - OK
return ( 0 );
};
The problem occurs when attempting to delete char* ArrayA in function Example1 because ArrayA is not a dynamic array. It will only be a dynamic array if it is equal to zero/null. So, to resolve that I created a similar function - Example2. The only difference is that Example2 has a boolean that checks to see if char* ArrayB is a dynamic array or not.
I know what I am doing is either incorrect or "noobish". So please help me. I will learn from my mistake.
How would you do it?
void Example3( char* ArrayC, unsigned int Length );
Maybe you could use this:
void Example2( char* ArrayB, unsigned int Length )
{
std::vector< char > internalArray;
if ( ArrayB != 0 )
{
internalArray.assign( ArrayB, ArrayB + Length );
}
else
{
internalArray.resize( Length, 0x2 );
}
// Do whatever with internalArray !!! <-------
// No (!!!) clenup need
};
I know what I am doing is either incorrect or "noobish". So please help me.
My overall recommendation would be to move from using C arrays to using std::vector instead.
Your example1 is definitely bad, since it tries to free an array that isn't dynamically allocated - that is NEVER right. As explained elsewhere, if you call across a DLL boundary, you may also have different allocators, so if the memory was not allocated where it is being deleted, things will go wrong. Let whoever allocated it delete it. Preferrably by using already existing standard functionality, such as std::vector
Your example2 only uses delete on something that was created within the function, which is perfectly fine. It doesn't try to delete something that it doesn't know is allocated in the same allocator. Yet, a std::vector would certainly be easier to handle.