wondering how would I find the length of char array .
for example
char buffer[20];
buffer[0] = 0x01;
buffer[1] = 0x02;
buffer[3] = 0x00;
buffer[4] = 0x04;
buffer[5] = 0x01;
buffer[6] = 0x02;
buffer[7] = 0x00;
buffer[8] = 0x04;
std::cout << "the len of array = "<< strlen(buffer) << std::endl;
o/p = the len of array = 3
expected o/p = 8
NOw issue is zeros can occur anywhere in the array of character elements.and I need true len i.e 8
Arrays in C (or C++) don't keep track of how much data has been stored in them. If you want to know the size of the stored data (as opposed to the size of the array), you'll need to track that yourself in another variable, or use a sentinel (such as NULL) that marks the end of the stored data.
Alternately, since you appear to be using C++ (despite the C tag), you can use a std::vector or std::string which tracks the size for you.
In C++ you would use a std::vector<char> or a std::string. Both store the length independently of the data so can hold zeros in them.
Beware that 'c' style literal strings are always zero terminated, so the following code gives you an empty string because the NUL terminates the string construction early.
std:string foo("\0Hello, world!");
When you have an array, you can use sizeof to get the total memory used by the array.
char buffer[20];
//
// ...
//
size_t size = sizeof(buffer); // This gives you total memory needed to hold buffer.
size_t length = sizeof(buffer)/sizeof(char); // In this case size and length will be
// same since sizeof(char) is 1.
If you have an array of other types,
int buffer[20];
//
// ...
//
size_t size = sizeof(buffer); // This gives you total memory needed to hold buffer.
size_t length = sizeof(buffer)/sizeof(int); // The length of the array.
There are pitfalls to be aware of using sizeof to get the memory used by an array. If you pass buffer to a function, you lose the ability to compute the length of the array.
void foo(char* buffer)
{
size_t size = sizeof(buffer); // This gives you the size of the pointer
// not the size of the array.
}
void bar()
{
char buffer[20];
// sizeof(buffer) is 20 here. But not in foo.
foo(buffer);
}
If you need to be able to compute the length of the array at all times, std::vector<char> and std::string are better choices.
void foo(std::vector<char>& buffer)
{
size_t size = buffer.size() // size is 20 after call from bar.
}
void bar()
{
std::vector<char> buffer(20);
size_t size = buffer.size() // size is 20.
foo(buffer);
}
Related
Is it possible to have a pointer that points to the contiguous buffer that is used by a vector?
For example (see below please), here std::vector<unsigned char*> vec contains two differently sized unsigned char* pointers. I need to have a buffer pointer that points to all pushed data in this vector. I'd guess that this is possible as the standard guarantees that a vector uses a contiguous memory buffer, right?
P.S. are the two ways of printing the elements of the vector I use in this example fine? (the two for loops)
unsigned char* data1 = new unsigned char[3];
data1[0] = 'a';
data1[1] = 'b';
data1[2] = 'c';
unsigned char* data2 = new unsigned char[1];
data2[0] = 'x';
std::vector<unsigned char*> vec;
vec.push_back(data1);
vec.push_back(data2);
for (size_t i = 0; i < vec.size(); i++) {
std::cout << vec[i];
}
std::cout << "\n";
for (auto iter = vec.begin(); iter != vec.end(); iter++) {
std::cout << (*iter);
}
std::cout << "\n\n";
unsigned char* buffer = (unsigned char*) vec[0];
Does buffer point to all data in vec? i.e. buffer[0] = a, buffer[1] = b, buffer[2] = c, buffer[3] = x ?
Does buffer point to all data in vec? i.e. buffer[0] = a, buffer[1] = b, buffer[2] = c, buffer[3] = x?
It doesn't. It points to the beggining of the array stored in first element of the vector.
Are the two ways of printing the elements of the vector I use in this example fine?
They are not, those arrays are not null terminated, they can't be printed as strings.
Is it possible to have a pointer that points to the contiguous buffer that is used by a vector?
Yes, it's possible.
If you'd like a pointer that can correctly access all the data in the vector, including individual elements of the unsigned char array members you'd want:
unsigned char **buffer = vec.data();
And the access:
for(size_t i = 0; i < 3; i++)
std::cout << buffer[0][i]; //indexing like a 2D array, albeit unbalanced
//output: abc
std::cout << buffer[1][0]; //output: x
Note that I use a cycle to access each element of data1 instead of simply treating it like a string, and this is because it is not a string, aka a null terminated char array.
Needless to say that you will need to know how many elements are stored in each array.
Alternatively you can null terminate them:
unsigned char* data1 = new unsigned char[4];
//...
data1[3] = '\0';
And
unsigned char* data2 = new unsigned char[2];
//...
data2[1] = '\0';
Here printing them like strings:
std::cout << buffer[0];
std::cout << buffer[1];
Using a null terminator has the extra benefit of allowing you to know the size of the arrays at any time using strlen((char*)buffer[0]).
You want the data() method on vector. It will return a pointer to the data, assuming that the vector size is greater than zero. If it is zero, then data() will return something but using it is undefined.
Read https://en.cppreference.com/w/cpp/container/vector/data
What would be the best way to iterate through each byte of a void* buffer, and a assign a value to each depending on certain conditions?
unsigned int bufSize = 100; //could be any value
void* buffer = malloc(bufSize);
char* bufferPointer = static_cast<char*>(buffer);
for (unsigned int i = 0; i < bufSize; i++){
if (i % 2 == 0){
bufferPointer[i] = 0x00;
}
else{
bufferPointer[i] = 0xff;
}
}
buffer = static_cast<void*>(bufferPointer);
Why doesn't this work? I tried converting to a char* to iterate over each byte.
You need to cast the void* to an unsigned char*. You can then use pointer arithmetic to traverse the block of memory that you own, and set values by pointer dereference.
Remember that pointer arithmetic is only valid within arrays. For this purpose an object can be considered to be an array of length 1. Also, and perhaps confusingly, an array of N int elements will equate to an array of N * sizeof(int) unsigned char elements.
I have a vector of chars:
vector<char> bytesv;
I push 1024 chars to this vector in a loop (not important to the context) using push_back(char):
bytesv.push_back(c);
I know this vector has an exact value of 1024. It indeeds print 1024 when doing the following:
cout << bytesv.size() << "\n";
What I am trying to do: I need to transform this vector into a char array (char[]) of the same length and elements as the vector. I do the following:
char* bytes = &bytesv[0];
The problem: But when I print the size of this array, it prints 4, so the size is not what I expected:
cout << sizeof(bytes) << "\n";
Full code:
vector<char> bytesv;
for (char c : charr) { // Not important, there are 1024 chars in this array
bytesv.push_back(c);
}
cout << bytesv.size() << "\n";
char* bytes = &bytesv[0];
cout << sizeof(bytes) << "\n";
Prints:
1024
4
This obviously has to do with the fact that bytes is actually a char*, not really an array AFAIK.
The question: How can I safely transfer all the vector's contents into an array, then?
How can I safely transfer all the vector's contents into an array, then?
Allocate the required memory by using dynamic memory allocation.
size_t size = bytesv.size();
char* char_array = new char[size];
Copy the elements from the vector to the array.
for ( size_t i = 0; i < size; ++i )
char_array[i] = bytesv[i];
Make sure you deallocate the memory after you are done using it.
delete [] char_array;
Having said, that I realized that you mentioned in a comment,
My ultimate goal is to save these bytes to a file, using fstream, which requires an array of chars as far as I am concerned.
You don't need to copy the contents of the vector to an array to save them to an fstream. The contents of a std::vector are guaranteed to be in contiguous memory. You can just use:
outStream.write(bytesv.data(), bytesv.size());
sizeof(bytes) is the size of the pointer, not what it points to. Also,
char* bytes = &bytesv[0];
Doesn't transfer anything to an array, all you've done is saved a pointer to the beginning of the underlying array in std::vector.
To correctly move the data to an array you'll need to dynamically allocate an array. But the question is why would you do that? You already have a vector. It's like an array but about a billion times better.
How can I safely transfer all the vector's contents into an array, then?
There's no need to "transfer" (i.e. copy). You can access the vector's underlying storage as an array by using the data method.
char* arr = bytesv.data();
http://en.cppreference.com/w/cpp/container/vector/data
bytes is actually a char*, not really an array
The char* is not an array but a pointer to the first value in the array. You can get the number of elements in the array from bytesv.size()
sizeof(bytes) is always 4 because *bytes is a pointer and you are using a machine that uses 4-byte pointers.
You already know that you have 1024 bytes; just use that knowledge.
First of all: you need to copy the content of the vector to the array - otherwise you can't access elements of your array, when the vector is gone. So you need to allocate memory to your array (not just defining a pointer).
char* bytes = new char[bytesv.size()];
for (size_t i = 0; i < bytesv.size(); ++i) {
bytes [i] = bytesv.at(i);
}
//...
delete[] bytes;
Secondly sizeof() doesn't do what you expect: its not reporting the length of an array, but the size of a type/pointer. In case of stack allocated arrays, it can be used as: sizeof(array)/sizeof(array[0]); to determine the size, but as sizeof() is a compile time operator it can't know the size of your dynamic allocated arrays or vectors.
If you use an array, you need to use a seperate variable to store the length of this array (alternatively you could use std::array instead).
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char* argv[]){
std::vector<uint8_t> bytesv = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
size_t bytesLength = bytesv.size();
char* bytes = new char[bytesLength];
for (size_t i = 0; i < bytesv.size(); ++i) {
bytes[i] = bytesv.at(i);
}
//...
std::cout << bytesLength << std::endl;
delete[] bytes;
return 0;
}
That's because the sizeof any pointer is 4 (on a 32 bit target). What
char* bytes = &bytesv[0];
is giving you is a pointer to the first element, not, necessarily, an array of chars.
now if you used:
char (*bytes)[1024] = (char (*)[1024])&v[0];
std::cout << sizeof(bytes) << " " << sizeof(*bytes);
that would give you a pointer to a 'char[1024]' array.
I have a function that allocated a buffer for the size of a file with
char *buffer = new char[size_of_file];
The i loop over the buffer and copy some of the pointers into a subbuffer to work with smaller units of it.
char *subbuffer = new char[size+1];
for (int i =0; i < size; i++) {
subbuffer[i] = (buffer + cursor)[i];
}
Next I call a function and pass it this subbuffer, and arbitrary cursor for a location in the subbuffer, and the size of text to be abstracted.
wchar_t* FileReader::getStringForSizeAndCursor(int32_t size, int cursor, char *buffer) {
int wlen = size/2;
#if MARKUP_SIZEOFWCHAR == 4 // sizeof(wchar_t) == 4
uint32_t *dest = new uint32_t[wlen+1];
#else
uint16_t *dest = new uint16_t[wlen+1];
#endif
char *bcpy = new char[size];
memcpy(bcpy, (buffer + cursor), size+2);
unsigned char *ptr = (unsigned char *)bcpy; //need to be careful not to read outside the buffer
for(int i=0; i<wlen; i++) {
dest[i] = (ptr[0] << 8) + ptr[1];
ptr += 2;
}
//cout << "size:: " << size << " wlen:: " << wlen << " c:: " << c << "\n";
dest[wlen] = ('\0' << 8) + '\0';
return (wchar_t *)dest;
}
I store this in a value as the property of a struct whilst looping through the file.
My issue seems to be when I free subbuffer, and start reading the title properties of my structs by looping over an array of struct pointers, my app segfaults. GDB tells me it finished normally though, but a bunch of records that I cout are missing.
I suspect this has to do with function scope of something. I thought the memcpy in getStringForSizeAndCursor would fix the segfault since it's copying bytes outside of subbuffer before I free. Right now I would expect those to then be cleaned up by my struct deconstructor, but either things are deconstructing before I expect or some memory is still pointing to the original subbuffer, if I let subbuffer leak I get back the data I expected, but this is not a solution.
The only definite error I can see in your question's code is the too small allocation of bcpy, where you allocate a buffer of size size and promptly copy size+2 bytes to the buffer. Since you're not using the extra 2 bytes in the code, just drop the +2 in the copy.
Besides that, I can only see one suspicious thing, you're doing;
char *subbuffer = new char[size+1];
and copying size bytes to the buffer. The allocation hints that you're allocating extra memory for a zero termination, but either it shouldn't be there at all (no +1) or you should allocate 2 bytes (since your function hints to a double byte character set. Either way, I can't see you zero terminating it, so use of it as a zero terminated string will probably break.
#Grizzly in the comments has a point too, allocating and handling memory for strings and wstrings is probably something you could "offload" to the STL with good results.
I want to create jagged character two dimensional array in c++.
int arrsize[3] = {10, 5, 2};
char** record;
record = (char**)malloc(3);
cout << endl << sizeof(record) << endl;
for (int i = 0; i < 3; i++)
{
record[i] = (char *)malloc(arrsize[i] * sizeof(char *));
cout << endl << sizeof(record[i]) << endl;
}
I want to set record[0] for name (should have 10 letter), record[1] for marks (should have 5 digit mark )and record[3] for Id (should have 2 digit number). How can i implement this? I directly write the record array to the binary file. I don't want to use struct and class.
in C++ it would like this:
std::vector<std::string> record;
Why would you not use a struct when it is the sensible solution to your problem?
struct record {
char name[10];
char mark[5];
char id[2];
};
Then writing to a binary file becomes trivial:
record r = get_a_record();
write( fd, &r, sizeof r );
Notes:
You might want to allocate a bit of extra space for NUL terminators, but this depends on the format that you want to use in the file.
If you are writing to a binary file, why do you want to write mark and id as strings? Why not store an int (4 bytes, greater range of values) and a unsigned char (1 byte)
If you insist on not using a user defined type (really, you should), then you can just create a single block of memory and use pointer arithmetic, but beware that the binary generated by the compiler will be the same, the only difference is that your code will be less maintainable:
char record[ 10+5+2 ];
// copy name to record
// copy mark to record+10
// copy id to record+15
write( fd, record, sizeof record);
Actually the right pattern “to malloc” is:
T * p = (T *) malloc(count * sizeof(T));
where T could be any type, including char *. So the right code for allocating memory in this case is like that:
int arrsize[3] = { 10, 5, 2 };
char** record;
record = (char**) malloc(3 * sizeof(char *));
cout << sizeof(record) << endl;
for (int i = 0; i < 3; ++i) {
record[i] = (char *) malloc(arrsize[i] * sizeof(char));
}
I deleted cout'ing sizeof(record[i]) because it will always yield size of (one) pointer to char (4 on my laptop). sizeof is something that plays in compiling time and has no idea how much memory pointed by record[i] (which is really a pointer - char * type) was allocated in the execution time.
malloc(3) allocates 3 bytes. Your jagged array would be an array containing pointers to character arrays. Each pointer usually takes 4 bytes (on a 32-bit machine), but more correctly sizeof(char*), so you should allocate using malloc(3 * sizeof(char*) ).
And then record[i] = (char*)malloc((arrsize[i]+1) * sizeof(char)), because a string is a char* and a character is a char, and because each C-style string is conventionally terminated with a '\0' character to indicate its length. You could do without it, but it would be harder to use for instance:
strcpy(record[0], name);
sprintf(record[1], "%0.2f", mark);
sprintf(record[2], "%d", id);
to fill in your record, because sprintf puts in a \0 at the end. I assumed mark was a floating-point number and id was an integer.
As regards writing all this to a file, if the file is binary why put everything in as strings in the first place?
Assuming you do, you could use something like:
ofstream f("myfile",ios_base::out|ios_base::binary);
for (int i=0; i<3; i++)
f.write(record[i], arrsize[i]);
f.close();
That being said, I second Anders' idea. If you use STL vectors and strings, you won't have to deal with ugly memory allocations, and your code will probably look cleaner as well.