Why we can do something like
for(int i = 0; i < destination->imageSize; i=i+3)
{
buffer[2] = destination->imageData[i];
buffer[1] = destination->imageData[i+1];
buffer[0] = destination->imageData[i+2];
buffer+=3;
}
but we can not do
char buffer[destination->imageSize];
And how to such thing?
Sorry - I am quite new to C++...
BTW: my point is to create a function that would return a char with an image. If I'd use mem copy how do I delete returned value?
I have to ask, why do you think they're at all related? If you couldn't index an array by runtime variable, it'd be pretty useless for there to even be arrays. Declaring a variable of a size governed by a runtime variable is entirely different and requires fundamental changes to the way the compiler manages automatic memory.
Which is why you can't do it in C++. This may change, but for now you can't.
If you really need a variable sized array you need to allocate one dynamically. You can do it the hard, f'd up way (char * buff = new char[size]...delete [] buff;), or you can do it the easy, safer way (std::vector<char> buff(size)). Your choice. You can't build it "on the stack" though.
char buffer[destination->imageSize]; declares a variable at compile time. At that time, the value of destination->imageSize is not yet known, which is why it doesn't work.
The expression buffer[2] = destination->imageData[i]; (or rather the buffer[2] thereof) is evaluated at run time.
You cannot return a local array. Everything you return will need to be free'd by someone.
The size of a local array must be constant. Always. This is because there is no special logic around arrays in C++. You can use some object collection of STL.
Hmm. Did you try creating a pointer or reference to destination->imageSize and passing that in for the index instead?
Using std::vector you can achieve what you desire. Your function can be defined something like this:
void readImage(std::vector<char>& imageData, std::string& filename)
{
size_t imageSize = 0;
//read file and load imageSize
imageData.resize(imageSize);
// load image into imageData using such as you in your question
for(int i = 0; i < destination->imageSize; i=i+3)
{
buffer[2] = destination->imageData[i];
buffer[1] = destination->imageData[i+1];
buffer[0] = destination->imageData[i+2];
buffer+=3;
}
}
For further improvements you could return a bool that indicates success or failure.
Regarding the cause of C2466, I don't have the official answer but you can declare char arrays with const variables only like so:
const int imageSize = 4242;
char imageData[imageSize]; // No C2466 error
Related
Unlike in the C, as what i've learned about C++, there is no instruction realloc in C++ for it is not recommended. But when I was creating a function that concatenates strings and at the same time can be dynamically re-allocating the given strings' memory without using vector, I've come to need some code just like as the realloc instruction functioning.
So what i've come up with is that using a reference of a pointer(in the code char* &des) could adjust the size of memory by using the usual instruction of C++, new and delete. However, an error occured: "[Error] invalid initialization of non-const reference of type 'char*&' from an rvalue of type 'char*'" Why is it impossible to initialize char*& type with the type char*? Isn't it the same as a statement char* &des = str0? The total code is as follows:
void Mystrcat(char* &des, const char* src) {
int des_len = Mystrlen(des); // Mystrlen just returns the length of a string with the type unsigned int excluding null character
int src_len = Mystrlen(src);
char* temp_str = des;
des = new char[des_len + src_len + 1];
//a copy process
for(int i = 0; i < des_len; i++) {
des[i] = *(temp_str + i);
}
for(int i = des_len + 1; i < des_len + src_len + 1; i++)
des[i - 1] = *(src + i - des_len - 1);
}
int main() {
char str0[100] = "Hello";
Mystrcat(str0, ", World!");
std::cout << str0 << std::endl; //expecting "Hello, World!" to be printed
return 0;
}
What i've tried before is just writing the parameter char* des instead of char* &des. But unlike in main function, it was not possible to get the size of total str0 array in Mystrcat function by simply using sizeof. As a result, I thought it would be good to use pointer reference. I was expecting this a reference of a pointer parameter to be working properly because it is equal to the statement char* &des = str0.
The problem here is:
char str0[100] = "Hello";
str in this case has a pinned (static) memory address. It's immutable in terms of its address -- so to speak -- because it's not a pointer to a string, but an array of characters of a size that can be evaluated at compile-time (not dynamically allocated). Making str itself point to a different address makes no sense and invites a whole lot of chaos. Even modifying the original pointer address to a dynamically-allocated array is chaos since you need the original address to properly free it. Think of an array of T as T* const (the address is immutable even if the contents are mutable and even if dynamically allocated, you need to keep the original address unmodified).
But in general as a non-profit advertisement of sorts, I want to encourage embracing value semantics as much as you can over pointer/reference ones. So instead of:
void Mystrcat(char* &des, const char* src)
{
// Modify the address of 'des' in place.
}
You can do:
[[nodiscard]] char* Mystrcat(char* des, const char* src)
{
// Input an address to a string and return an address to a new string.
}
Then you can pass an address to your array, get a pointer to a new modified copy (same thing you were doing before), and store the pointer to the new array (along with freeing it when you're done). There's little benefit to modifying things in place if you're just going to allocate a new string anyway.
This is still ignoring the conventional advice that you should use std::string which is what I think you need now and wholeheartedly echo over all this low-level pointer stuff and manual heap allocation and deallocation (which can be disastrous without the use of RAII when combined with thrown exceptions) But later you might want to deviate from it if the SBO is too large or too small or if the SBO optimization is counter-productive, for example but that's diving deep into things like custom memory allocators and whatnot and something you typically reserve until you encounter profiler hotspots and really know what you're doing.
I'm in the process of refactoring some old code. There's a C style function that works like this: (Obviously I've simplified it here)
int LoadData(char** buf1, int* buf1Len, char** buf2, int* buf2Len) {
*buf1Len = DetermineLength1();
*buf1 = (char*)malloc(*buf1Len);
// Fill buf1
*buf2Len = DetermineLength2();
*buf2 = (char*)malloc(*buf2Len);
// Fill buf2
int result = 0; // Or some other INT depending of result
return result;
}
Now, I'd like to update this code to somehow return a unique_ptr or equivalent, so the pointer will be automatically managed by the caller, and the caller won't ever forget to free the memory.
I couldn't find a good solution, so currently I've changed the code to the following:
int LoadData(std::unique_ptr<char[]>* ubuf1, int* buf1Len, std::unique_ptr<char[]>* ubuf2, int* buf2Len) {
// same code as above, and finally:
ubuf1->reset(buf1);
ubuf2->reset(buf2);
return result;
}
This doesn't look good, so I'm looking to see if there's a better solution. Since I'm returning two buffers, using the unique_ptr as the return value is not an option.
Is there any better way for this?
Don't use std::unique_ptr for arrays if you don't have to. The proper tool for storing dynamic arrays is usually std::vector. It packs the size information right along with the object, where it belongs. If your char* are being used as strings, then you might want to use std::string instead.
std::pair<std::vector<char>, std::vector<char>>
LoadData()
{
std::vector<char> buf1(DetermineLength1());
// Fill buf1
std::vector<char> buf2(DetermineLength2());
// Fill buf2
return { std::move(buf1), std::move(buf2) };
}
If you still need your int return result, then you can change the function to return std::tuple<int, std::vector<char>, std::vector<char>>. Or better yet, create a struct with meaningful names for the members.
I'm searching for an example or explanation why someone should (or should not) use triple-pointers in C/C++.
Are there any examples where triple-pointer arise?
I am especially looking for source-code which uses triple-pointers.
The best example that comes to mind is a sparse multi-level table. For instance one way to implement properties for Unicode characters might be:
prop_type ***proptable;
...
prop_type prop = proptable[c>>14][c>>7&0x7f][c&0x7f];
In this case proptable would need to have a triple-pointer type (and possibly quadruple pointer if the final resulting type is a pointer type). The reason for doing this as multiple levels rather than one flat table is that, at the first and second levels, multiple entries can point to the same subtable when the contents are all the same (e.g. huge CJK ranges).
Here's another example of a multi-level table that I implemented; I can't say I'm terribly proud of the design but given the constraints the code has to satisfy, it's one of the least-bad implementation choices:
http://git.musl-libc.org/cgit/musl/tree/src/aio/aio.c?id=56fbaa3bbe73f12af2bfbbcf2adb196e6f9fe264
If you need to return an array of pointers to variable length strings via a function parameter:
int array_of_strings(int *num_strings, char ***string_data)
{
int n = 32;
char **pointers = malloc(n * sizeof(*pointers));
if (pointers == 0)
return -1; // Failure
char line[256];
int i;
for (i = 0; i < n && fgets(line, sizeof(line), stdin) != 0; i++)
{
size_t len = strlen(line);
if (line[len-1] == '\n')
line[len-1] = '\0';
pointers[i] = strdup(line);
if (pointers[i] == 0)
{
// Release already allocated resources
for (int j = 0; j < i; j++)
free(pointers[j]);
free(pointers);
return -1; // Failure
}
}
*num_strings = i;
*string_data = pointers;
return 0; // Success
}
Compiled code.
If you use a linked list you have to store the address of the first element of the list ( first pointer ) .
If you need to change in that list you need another pointer ( two pointer)
If you need to pass your list that you are changing in two pointers and change it in another function you need another pointer ( three pointer )...
They are a lots of examples
I've used triple pointers in C++:
There is an interface written for a Java program:
https://github.com/BenLand100/SMART/blob/master/src/SMARTPlugin.h
and it takes an array of strings.
typedef void (*_SMARTPluginInit)(SMARTInfo *ptr, bool *replace, int *buttonc, char ***buttonv, int **buttonid, _SMARTButtonPressed *buttonproc);
Then in my program I do:
char* btnTexts[2] = {"Disable OpenGL_Enable OpenGL", "Enable Debug_Disable glDebug"}; //array of C-style strings.
void SMARTPluginInit(SMARTInfo* ptr, bool* ReplaceButtons, int* ButtonCount, char*** ButtonTexts, int** ButtonIDs, _SMARTButtonPressed* ButtonCallback)
{
*ButtonText = btnTexts; //return an array of strings.
}
but in C++, you can use a reference instead of pointer and it'd become:
void SMARTPluginInit(SMARTInfo* ptr, bool* ReplaceButtons, int* ButtonCount, char** &ButtonTexts, int** ButtonIDs, _SMARTButtonPressed* ButtonCallback)
{
ButtonText = btnTexts; //return an array of strings.
}
Notice now that "ButtonTexts" is a reference to an array of C-style strings now.
A char*** can be a pointer to an array of C-style strings and that's one time that you'd use it.
A very simple example is a pointer to an array of arrays of arrays.
Triple pointer is a pointer variable that points to a pointer which in turn points to another pointer. The use of this complex programming technique is that usually in which companies process tons and tons of data at one time .A single pointer would point to a single block of data (suppose in a large file) using the triple pointer would result in 3 times faster processing as different blocks of data(in the same file) can be pointed by different pointer and thus data could be accessed/processed faster (unlike 1 pointer going through the whole file).
[edit] Outside of this get method (see below), i'd like to have a pointer double * result; and then call the get method, i.e.
// Pull results out
int story = 3;
double * data;
int len;
m_Scene->GetSectionStoryGrid_m(story, data, len);
with that said, I want to a get method that simply sets the result (*&data) by reference, and does not dynamically allocate memory.
The results I am looking for already exist in memory, but they are within C-structs and are not in one continuous block of memory. Fyi, &len is just the length of the array. I want one big array that holds all of the results.
Since the actual results that I am looking for are stored within the native C-struct pointer story_ptr->int_hv[i].ab.center.x;. How would I avoid dynamically allocating memory like I am doing above? I’d like to point the data* to the results, but I just don’t know how to do it. It’s probably something simple I am overlooking… The code is below.
Is this even possible? From what I've read, it is not, but as my username implies, I'm not a software developer. Thanks to all who have replied so far by the way!
Here is a snippet of code:
void GetSectionStoryGrid_m( int story_number, double *&data, int &len )
{
std::stringstream LogMessage;
if (!ValidateStoryNumber(story_number))
{
data = NULL;
len = -1;
}
else
{
// Check to see if we already retrieved this result
if ( m_dStoryNum_To_GridMap_m.find(story_number) == m_dStoryNum_To_GridMap_m.end() )
{
data = new double[GetSectionNumInternalHazardVolumes()*3];
len = GetSectionNumInternalHazardVolumes()*3;
Story * story_ptr = m_StoriesInSection.at(story_number-1);
int counter = 0; // counts the current int hv number we are on
for ( int i = 0; i < GetSectionNumInternalHazardVolumes() && story_ptr->int_hv != NULL; i++ )
{
data[0 + counter] = story_ptr->int_hv[i].ab.center.x;
data[1 + counter] = story_ptr->int_hv[i].ab.center.y;
data[2 + counter] = story_ptr->int_hv[i].ab.center.z;
m_dStoryNum_To_GridMap_m.insert( std::pair<int, double*>(story_number,data));
counter += 3;
}
}
else
{
data = m_dStoryNum_To_GridMap_m.find(story_number)->second;
len = GetSectionNumInternalHazardVolumes()*3;
}
}
}
Consider returning a custom accessor class instead of the "double *&data". Depending on your needs that class would look something like this:
class StoryGrid {
public:
StoryGrid(int story_index):m_storyIndex(story_index) {
m_storyPtr = m_StoriesInSection.at(story_index-1);
}
inline int length() { return GetSectionNumInternalHazardVolumes()*3; }
double &operator[](int index) {
int i = index / 3;
int axis = index % 3;
switch(axis){
case 0: return m_storyPtr->int_hv[i].ab.center.x;
case 1: return m_storyPtr->int_hv[i].ab.center.y;
case 2: return m_storyPtr->int_hv[i].ab.center.z;
}
}
};
Sorry for any syntax problems, but you get the idea. Return a reference to this and record this in your map. If done correctly the map with then manage all of the dynamic allocation required.
So you want the allocated array to go "down" in the call stack. You can only achieve this allocating it in the heap, using dynamic allocation. Or creating a static variable, since static variables' lifecycle are not controlled by the call stack.
void GetSectionStoryGrid_m( int story_number, double *&data, int &len )
{
static g_data[DATA_SIZE];
data = g_data;
// continues ...
If you want to "avoid any allocation", the solution by #Speed8ump is your first choice! But then you will not have your double * result; anymore. You will be turning your "offline" solution (calculates the whole array first, then use the array elsewhere) to an "online" solution (calculates values as they are needed). This is a good refactoring to avoid memory allocation.
This answer to this question relies on the lifetime of the doubles you want pointers to. Consider:
// "pointless" because it takes no input and throws away all its work
void pointless_function()
{
double foo = 3.14159;
int j = 0;
for (int i = 0; i < 10; ++i) {
j += i;
}
}
foo exists and has a value inside pointless_function, but ceases to exist as soon as the function exits. Even if you could get a pointer to it, that pointer would be useless outside of pointless_function. It would be a dangling pointer, and dereferencing it would trigger undefined behavior.
On the other hand, you are correct that if you have data in memory (and you can guarantee it will live long enough for whatever you want to do with it), it can be a great idea to get pointers to that data instead of paying the cost to copy it. However, the main way for data to outlive the function that creates it is to call new, new[], or malloc. You really can't get out of that.
Looking at the code you posted, I don't see how you can avoid new[]-ing up the doubles when you create story. But you can then get pointers to those doubles later without needing to call new or new[] again.
I should mention that pointers to data can be used to modify the original data. Often that can lead to hard-to-track-down bugs. So there are times that it's better to pay the price of copying the data (which you're then free to muck with however you want), or to get a pointer-to-const (in this case const double* or double const*, they are equivalent; a pointer-to-const will give you a compiler error if you try to change the data being pointed to). In fact, that's so often the case that the advice should be inverted: "there are a few times when you don't want to copy or get a pointer-to-const; in those cases you must be very careful."
D3DFORMAT *arr = NULL;
This is the reference to the array which is supposed to hold D3DFORMAT typed values.
How do I allocate the memory for this array whose size is defined by a variable
unsigned int arrsize;
Should I calculate the size of array in bytes as = sizeof(D3DFORMAT)*arrsize;
And than use memset().?
Plz correct me if I am wrong. Or if tere is a cleaner better C++ method to do this. ?
IN advance. Thanks
"cleaner better C++ method" is to use a std::vector
unsigned int arrsize = 10;
std::vector <D3DFORMAT> array (arrsize );
to cast it to void*
void* p = (void*)(&array[0]);
you will also want to have your values be 0 by default, so just add one more parameter to the constructor
unsigned int arrsize = 10;
std::vector <D3DFORMAT> array (arrsize, 0);
Like this
D3DFORMAT* arr = new D3DFORMAT[arrsize];
memset might work, or it might crash your program. It all depends on how D3DFORMAT has been defined. Can you post the definition of D3DFORMAT?
Just noticed you asked for a better method. The better method very likely is
std::vector<D3DFORMAT> arr(arrsize);
but again, it does depend on how D3DFORMAT is defined.