I have a byte array serialized from a stream char* Buf which points to an array of 64 bytes.
I wish to cast it into a function input parameter Foo(char[4][16] Buf) without copying each and every single bytes.
Any easy for doing so?
You can cast any buffer to any array you want:
void Foo(char(&buf)[4][16])
{
}
int main()
{
char* buf = new char[64];
Foo((char(&)[4][16])(buf));
delete[] buf;
return 0;
}
I found the answer in link given by Michael Chourdakis
*reinterpret_cast<char(*)[4][16]>(Buf)
Related
How can I write in C++ a function who put the data in a char array, I don't how to explain well but I'll write an example
void functionCopyData(char& buf){
// get data from a char variable
char data1 = "textdata1";
char data2 = "textdata2"
// copy data
copy(&buf,data1);
copy(&buf,data2);
}
char variable[20];
functionCopyData(&variable);
printf(variable);
// return: textdata1textdata2
So summarizing, I need to copy the data from two variables and put in a char array. Sorry if I was not clear enough.
Why this way?
because I need to get the data from and a variable and send it in a function request a reference data sendFunction(&data,sizeVar);
how can I do that?
How can I write in C++ a function who put the data in a char array
Change the argument type.
void functionCopyData(char& buf){
will be good if you want to update just one character, not an array of characters. To update an array of characters, use:
void functionCopyData(char buf[]){
or
void functionCopyData(char* buf){
That could easily lead to problems if buf does not have enough memory to store the data. To make function more robust, pass a number that indicates the capacity of buf.
void functionCopyData(char buf[], size_t capacity){
Fix the definitions of data1 and data2.
char data1 = "textdata1";
char data2 = "textdata2"
are not syntactically valid. Change them to:
char data1[] = "textdata1";
char data2[] = "textdata2";
or
char const* data1 = "textdata1";
char const* data2 = "textdata2";
Make sure that buf can hold data1 and data2.
// You need the additional 1 for the terminating null
// character.
size_t capacityNeeded = strlen(data1) + strlen(data2) + 1;
if ( capacityNeeded > capacity )
{
// Deal with the problem.
}
else
{
// Now copy the contents of data1 and data2 to buf
}
Copy the contents data1 and data2 to buf using standard library functions.
strcpy(buf, data1);
strcat(buf, data2);
Fix the call to the function.
functionCopyData(&variable);
is not the right syntax to use to call the function, given the function declaration. Use:
functionCopyData(variable, 20);
An easy solution is to write a function to copy one array, and then call it twice with different pointers pointing to different positions in the result array.
For example, if you have char data[20] to hold the result, and want to copy two arrays char a[10] and char b[10], then write a function
void copy(char* destination, char* source, int length)
That copies length bytes from source to destination, then call it with
copy(data, a, 10);
copy(data+10, b, 10);
The functions strcpy and strlen can help you:
#include <string.h>
void functionCopyData(char buf[]){
char data1[] = "textdata1";
char data2[] = "textdata2";
strcpy(buf, data1);
strcpy(buf+strlen(buf), data2);
}
...
functionCopyData(variable);
...
void functionCopyData(char* buf){
// get data from a char variable
char* data1 = "textdata1";
char* data2 = "textdata2"
// copy data
copy(buf,data1);
copy(buf,data2);
}
char variable[20];
functionCopyData(variable);
printf(variable);
I think it's more clear use pointer but not reference.
My problem is that I don't know how to convert int value to char array char* m_value. I tried to use itoa but it doesn't work. itoa(m_val, m_wartosc, 10); Maybe there is some other function to do this ?
Main.cpp
int main(int argc, char *argv[])
{
LargeNumber l1;
LargeNumber l3(172839); //how to convert this int to char*
return 0;
}
LargeNumber.h
class LargeNumber{
public:
LargeNumber()
{
m_array = "0"; //zero for no arg.
}
LargeNumber(int val):m_val(val)
{
itoa(m_val, m_array, 10); //doesn't work
//sprintf(m_array, "%d", m_val);
}
LargeNumber(const LargeNumber& p):m_array(p.m_array)
{ } //copy constructor
~LargeNumber(){
delete []m_array; //for object with new
}
public: //should be private
int m_val;
char* m_array;
};
The simple answer is: don't. For two reasons:
As you can see from all the (wrong) other answers, memory management is tricky and bug-prone.
I can't see how storing your value in base-10, in an ASCII string, could possibly be useful. (Compared to, say, a base-232 representation.)
But if you really must store it this way, you will need to allocate the relevant amount of memory, use snprintf to convert (itoa is a non-standard function), and remember to free the memory at the correct time(s) (you will have to read and understand about the Rule of Three).
I would strongly recommend using a std::string instead of a raw C-style array, because it will at least deal with its own memory management, and you will then be able to populate it with a std::stringstream.
The second argument of itoa() needs to be an array in memory large enough to store the null-terminated string. An example:
int number = 172839;
char buffer[10];
itoa(number,buffer,10);
LargeNumber(int val):m_val(val)
{
std::stringstream stream;
stream << val;
m_array = new char[stream.str().size()];
strcpy(m_array, stream.str().c_str());
}
You have to first allocate the array with
m_array = new char[20]
in constructor before calling iota.
the iota doesnt allocate memory.
I want to copy a char to an address where a given char* points to.
it's in a function which is called by main:
char data = " ";
myfunction(data, somethingelse);
...
inside the function i have something like
void myfunction(char* data, short somethingelse) {
...
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++;
...
}
the segfault also comes when i to the copy using strncpy:
strncpy(data, byte, 1);
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array. i've tested that multiple times.
thanks in advance.
String literals are readonly. If you want a modifyable string, you must use an array, e.g.:
char data[10];
Or:
char *data = new char[10];
To elaborate a bit more: the type of a string literal is actually const char*. Assigning a string literal to a non-const char* is therefore technically invalid, but most compilers allow it anyway for legacy reasons. Many modern compilers will at least issue a warning when you try to do that.
data is assigned a string literal. String literals are ready only, and writing to them will cause segfaults.
Try this:
char data[10]; // or whatever size you want.
instead.
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array.
You didn't allocate anything. char *data = " "; shouldn't even compile in C++. You are assigning a constant string to a non-constant.
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++; // << How many times?
No problem
#include <stdio.h>
int main(int argc, char **argv)
{
char *data = "Yello"; // or char data[] = "Yello";
*data = 'H';
puts(data); // Hello
}
I am to the point I am confusing myself but here is what I have. I have only recently started to familiarize myself with pointers more to a point I feel more comfortable using them, but I am getting an error about the buffer in strcpy_s() being too small.
Please no comments about me using char arrays instead of std::string, its for the HL2SDK which centers around char arrays (no idea why) so I just stick to the pattern.
void func_a()
{
char *szUserID = new char[64];
char *szInviterID = new char[64];
char *szGroupID = new char[64];
sprintf(szUserID, "%I64d", GetCommunityID(szUserSteamID));
sprintf(szInviterID, "%I64d", GetCommunityID(g_CvarSteamID.GetString()));
GetGroupCommunityID(1254745, &szGroupID); // Group Steam Community ID
}
void GetGroupCommunityID(int groupID, char **communityID)
{
int staticID = 1035827914;
int newGroupID = 29521408 + groupID;
char *buffer = new char[64];
snprintf(buffer, sizeof(buffer), "%d%d", staticID, newGroupID);
strcpy_s(*communityID, sizeof(*communityID), buffer);
delete buffer;
}
The problem is you are using sizeof which is a compile time construct to determine the runtime length of *communityID. This will essentially resolve down to sizeof(char*). What you want though is the number of bytes / chars available in *communityID. This information needs to be passed along with the value
GetGroupCommunityID(1254745, &szGroupID, sizeof(szGroupID));
void GetGroupCommunityID(int groupId, char** communityID, size_t length) {
...
strcpy_s(*communityID, length, buffer);
}
Also in this example a double pointer is unnecessary because you're not changing the pointer, just it's contents. A single pointer will do just fine for that
GetGroupCommunityID(1254745, szGroupID, sizeof(szGroupID));
void GetGroupCommunityID(int groupId, char* communityID, size_t length) {
...
strcpy_s(communityID, length, buffer);
}
If you are using constants values (char *szGroupID = new char[64]) why not declare a constant with the value 64 and use this value; by the way sizeof(szGroupID) is going to return 4 bytes too in a 32 bits compiler.
The second parameter to strcpy_s is the actual size (number of characters) of the buffer pointed to by the first parameter. sizeof(*communityID) only gives you the size of a char * pointer, typically 4 bytes on a 32-bit system. You need to pass in the actual size of *communityID to the GetGroupCommunityID function and pass this on to strcpy_s.
I am trying to allocate a char array of size 1000. This array
is passed to a function where it should be filled with the data
that has been received from the TCP Socket. The problem occurs
then when I try to delete[] buffer: Here I get as a result a User
Panic 42. Unfortunately, I do not really see what is going wrong
in this simple code fragement...
int main
{
unsigned char *buffer = new unsigned char[1000];
Recv(&buffer);
delete[] buffer;
return (0);
}
void Recv(unsigned char **buffer)
{
TRequestStatus iStatus;
TSockXfrLength len;
TBuf8<1000> buff;
iSocket.RecvOneOrMore( buff, 0, iStatus, len );
User::WaitForRequest(iStatus);
*buffer = ( unsigned char* )buff.Ptr();
}
Thanks for any useful hints!
What Konrad says is true, but I don't think he knows Symbian. If you do need a function to read bytes into a char buffer, then a better fix would be:
void Recv(unsigned char *aBuffer, int aSize)
{
TRequestStatus iStatus;
TSockXfrLength len;
TPtr8 buff(aBuffer, aSize);
iSocket.RecvOneOrMore( buff, 0, iStatus, len );
User::WaitForRequest(iStatus);
}
TBuf8 is a descriptor which contains an array to hold the data. TPtr8 is a descriptor which refers to an external buffer that you specify. Either can be passed into RecvOneOrMore, since they both inherit from the parameter type, TDes8&. So the socket can be made to write its data directly into your buffer, instead of writing into a buffer on the stack and then copying as Konrad's code does.
You probably also need to check the status to detect errors, and report success/failure and the length written back to the caller.
Your array allocation is without effect because inside the function, you assign a new pointer to the array:
*buffer = ( unsigned char* )buff.Ptr();
Now the buffer points to another memory location, presumably one that you may not free using delete (e.g. one on the stack, or allocated using something other than new).
To fix the problem, it's probably best to copy the data to your array:
void Recv(unsigned char *buffer)
{
TRequestStatus iStatus;
TSockXfrLength len;
TBuf8<1000> buff;
iSocket.RecvOneOrMore( buff, 0, iStatus, len );
User::WaitForRequest(iStatus);
unsigned char* const tmpbuf = static_cast<char*>(buff.Ptr());
std::copy(tmpbuf, tmpbuf + len, buffer);
}
Notice that the buffer pointer is now passed directly to the function Recv, no further indirection needed since we don't manipulate the pointer directly.
Um, you're trying to delete[] something that's not allocated by you. You're delete[]ing buff.Ptr() while leaking the array allocated in main().