Valhalla Legends Forums Archive | C/C++ Programming | Question Regarding Arrays

AuthorMessageTime
Dyndrilliac
How would I redeclare a single dimensional array, so as to overwrite the old instance of it but preserve all the items in the array and increase the maximum number of indexes by one?

I am pretty much looking for the Visual Basic to C++ equivalent of "ReDim Preserve ArrayName(0 To UBound(ArrayName) + 1)"
January 31, 2005, 11:18 PM
Mephisto
Dynamically allocate the array using malloc and then when you want to increase it and preserve the current data use realloc on it.

Note: These are C methods of dynamic memory allocation, I don't know of any C++ methods of reallocating an array.
January 31, 2005, 11:21 PM
Dyndrilliac
Thanks
January 31, 2005, 11:47 PM
Dyndrilliac
Question, I looked up malloc() on MSDN and the parameter for it is the amount of bytes I want to make it in size; Is this the same as number of indexes?

Also, do I declare the array without any indexes then use malloc on it? Example:

[code]#include <stdlib.h>
#include <malloc.h>
#include <windows.h>

int main()
{
  char string[];
  string = (char *)malloc(5);

  if (string == NULL) {
      messagebox(NULL, "Insufficient Memory!", "Error!", MB_OK | MB_ICONERROR);
  } else {
      free(string);
  }

  return 0;
}[/code]
February 1, 2005, 12:19 AM
Myndfyr
[quote author=Dyndrilliac link=topic=10387.msg97695#msg97695 date=1107217168]
Question, I looked up malloc() on MSDN and the parameter for it is the amount of bytes I want to make it in size; Is this the same as number of indexes?
[/quote]
No!!!!!!!!!  [edit: added extra !s to emphasize that it's an important thing to know, not to be attitude-ish.]  You want to make the number of bytes equal the size of the object times the number of indices (note the CORRECT plural of "index") -- so:
[code]
char *pszString = (char*)malloc(5 * sizeof(char));
[/code]
In the case of char, it IS the number of indices; however, for larger data types, such as DWORD:
[code]
typedef unsigned long int DWORD;

DWORD *pDwordArray = (DWORD*)malloc(5 * sizeof(DWORD));
[/code]

[quote author=Dyndrilliac link=topic=10387.msg97695#msg97695 date=1107217168]
Also, do I declare the array without any indexes then use malloc on it? Example:

[code]#include <stdlib.h>
#include <malloc.h>
#include <windows.h>

int main( void )
{
   char string[];
   string = (char *)malloc(5);

   if (string == NULL) {
      messagebox(NULL, "Insufficient Memory!", "Error!", MB_OK | MB_ICONERROR);
   } else {
      free(string);
   }
}[/code]
[/quote]
The only way you can declare an array without a size (I *believe*) is to make it a pointer, like I did in my samples above.  Arrays and pointers are interchangeable; example code:

[code]
typedef unsigned long int DWORD;

int i;
DWORD *pDwordArray;
*pDwordArray = (DWORD*)malloc(5 * sizeof(DWORD));
for (i = 0; i < 5; i++)
{
  *(pDwordArray + i * sizeof(DWORD)) = i;
}
// that loop does the exact same as the one below:
for (i = 0; i < 5; i++)
{
  pDwordArray[i] = i;
}
[/code]
Recall order of operations; i*sizeof(DWORD) comes first, and so you're getting an offset into the memory that was allocated at pDwordArray.
February 1, 2005, 12:28 AM
UserLoser.
Correct me if I'm wrong, but isn't malloc supposed to be for C, while new is for C++?
February 1, 2005, 1:01 AM
Newby
Mephisto stated that, IIRC.

[quote author=Mephisto link=topic=10387.msg97677#msg97677 date=1107213681]
Dynamically allocate the array using malloc and then when you want to increase it and preserve the current data use realloc on it.

Note: These are C methods of dynamic memory allocation, I don't know of any C++ methods of reallocating an array.
[/quote]
February 1, 2005, 1:20 AM
Myndfyr
[quote author=UserLoser link=topic=10387.msg97707#msg97707 date=1107219682]
Correct me if I'm wrong, but isn't malloc supposed to be for C, while new is for C++?
[/quote]

Yes, new works.  But malloc is more generalizable; as C++ is a superset of C, malloc works equally well in C++ as it does in C.

Additionally, since he said he wanted to redeclare the array, malloc and its cousin realloc should be used.  As I understand it, realloc is the only way to have a fighting chance of not having to copy memory.  Example:
[code]
typedef unsigned long int DWORD;

// inside a function somewhere.
DWORD* pOriginalLoc, pDwordArray, pNewLoc;

pDwordArray = (DWORD*)malloc(5 * sizeof(DWORD));
pOriginalLoc = pNewLoc = pDwordArray; // copies ptr locations
realloc(pNewLoc, (size_t)(10 * sizeof(DWORD)));
if (pNewLoc == pOriginalLoc)
{
 // don't need to copy memory.
}
else
{
 // need to copy memory from the original.
}
[/code]
However:
[code]
DWORD* pOriginalLoc, pDwordArray, pNewLoc;
pDwordArray = new DWORD[5];
pOriginalLoc = pNewLoc = pDwordArray;
delete[] pDwordArray;
pNewLoc = new DWORD[10];
if (pNewLoc == pOriginalLoc)
{
 // don't need to copy memory -- except wait!
 // after calling delete[], the compiler is free to change the
 // contents of memory.  While it's not practical, you are not
 // guaranteed that the memory values will stay the same.
 // example: an optimizing compiler will figure out that pNewLoc
 // isn't actually accessed until AFTER the delete[] statement.
 // thus, it can put the value of pNewLoc in the first memory location
 // freed, in which case you will NEVER have this conditional
 // even be executed.  Particularly if this is on a global heap,
  // you can run into trouble, in which case another program may access
  // that memory and overwrite it while your thread is waiting.
}
else
{
 // need to copy memory
}
[/code]
February 1, 2005, 1:27 AM
Mephisto
Operator new just calls malloc() anyways.  But there are certain advantages to using new; three being that it's designed for use with C++ and should be used if you're using C++, it automatically returns the correct pointer type where malloc does not and it can be overloaded for custom functionality.  However, there are no specific C++ methods for re-allocating an array without losing its current contents (the contents will still be in memory, you just won't be able to access them) unless you want to copy memory which I believe you didn't want to do.
February 1, 2005, 3:15 AM
Arta
Bare in mind that realloc does not guarantee not to move your data anyway. Reallocation should always be considered a (relatively) expensive operation. IMHO, its use is often a sign of bad design - perhaps you should rethink your approach?
February 1, 2005, 4:54 AM
Dyndrilliac
Well, I need a method to add and remove indices from an array while preserving the data in it. I'm currently working on creating my own Plugin API using LoadLibrary, FreeLibrary, GetProcAddress, and GetModuleHandle.

The only part that's giving me problems is adding and removing plugin objects from the array that holds them. I decided to go with the method I learned in VB to add and remove data froman aray, because those are the only ways I know how.

Add: When the array is full, a dd new indices preserving everything in it, then add the new items.

Remove: Copy everything to a new temporary array except what I want to  remove, then reduce the number of indices on the original array by one and copy everything back.

I already have most of my functions and my Plugin Class written, so I really only need a way to manage the array of Plugin Objects
February 1, 2005, 3:28 PM
Arta
That doesn't sound very good. What happens when someone unloads a plugin in the middle fo the array? Won't all the plugins after it have their indices changed and mess everything up? Sounds like you want to use a linked list.
February 1, 2005, 4:03 PM
Adron
[quote author=Dyndrilliac link=topic=10387.msg97770#msg97770 date=1107271690]
Remove: Copy everything to a new temporary array except what I want to  remove, then reduce the number of indices on the original array by one and copy everything back.
[/quote]

This doesn't sound very efficient. If you're doing something like this, I don't see why you need reallocation. You just make a new array with one less spot than the original array, copy all the data there, then deallocate the original array and change your pointer to point to the new array. Same thing works for adding an entry, except you make the new array one bigger than the original.
February 1, 2005, 4:17 PM
Dyndrilliac
@Arta: Well, I thought about that - instead of locating plugins by their indices, I decided to use a handle that would be both global and accessible by the Application, and the Pliugin API - This way I could manage the plugins by this one variable and I could locate one in the array that I needed even when the indices changed. I decided to use the Plugin's Path for this, because it is the data that is passed from the App to the API making it globally and instantly accessible from the get-go.

However, following your suggestion, I googled linked-lists, and they look liike they would serve my purpose better than an array - However, it will take some practice to get it working :)

@Adron: Could you show me an example of this? I'm being exposed to a lot of new stuff in this thread :P

Anyway, to give you an idea what I'm working with, here's my Plugin class:[code]class Plugin { // Plugin Object Class
public:
Plugin(char* szPath);  // Constructor (Loads Plugin  and Initializes Object)
~Plugin();              // Destructor (Called on UnloadPlugin())
char* szplVers;        // Variable to hold Plugin Version
char* szplPath;        // Variable to hold Plugin Path
VERSIONPROC pVersion;  // Version() of the Plugin
protected:
LOADPROC pLoad;        // Load Event of the Plugin
UNLOADPROC pUnload;    // Unload Event of the Plugin
HINSTANCE hInst;        // Handle for Library Instance
};[/code]
February 1, 2005, 4:29 PM
Arta
If you write your own, linked lists can take a while to get right.  You might prefer to use STL - std::list is what you want, iirc. I'm not an STL person though so perhaps you should ask someone else (eibro?)
February 1, 2005, 4:51 PM
Adron
std::list works. If you have handles associated with each item and want to access them by handle you might want to use a std::map<handle,item> instead.

Example of deletion by moving things from old array to new array:

[code]
item *array;
int size;

void DeleteItem(int index)
{
  item *newarray = 0;
  if(--size) {
    int i, j;
    newarray = new item[size];
    for(i = j = 0; j < size; i++)
      if(i != index) newarray[j++] = array[i];
  }
  delete [] array;
  array = newarray;
}
[/code]
February 1, 2005, 6:09 PM
Mephisto
[quote author=Arta[vL] link=topic=10387.msg97776#msg97776 date=1107276679]
If you write your own, linked lists can take a while to get right.  You might prefer to use STL - std::list is what you want, iirc. I'm not an STL person though so perhaps you should ask someone else (eibro?)
[/quote]

While you are correct, there are certain situations where realloc would be a good thing.  For instance, when inserting data into a buffer that may be of unknown size and you run out of room to insert data, it'd be better IMO to resize the buffer to make room then fail the operation as failing the operation may result in a terminal error (such as failing the Battle.net protocol for a bot).
February 1, 2005, 8:00 PM
Zakath
It's definitely worth it to learn how to make a linked list. It's an invaluable construct. I highly advise doing it that way.
February 1, 2005, 10:25 PM
Adron
[quote author=Mephisto link=topic=10387.msg97796#msg97796 date=1107288013]
While you are correct, there are certain situations where realloc would be a good thing.  For instance, when inserting data into a buffer that may be of unknown size and you run out of room to insert data, it'd be better IMO to resize the buffer to make room then fail the operation as failing the operation may result in a terminal error (such as failing the Battle.net protocol for a bot).
[/quote]

This sounds like jibberish? Did you read what everyone has been saying? Did you understand that calling "realloc" in many cases will result in a new allocation and copying of data, and that that's what we're talking about? Did anyone at any time suggest to just fail because your fixed size buffer is full?

Also, you shouldn't assume that you will be able to resize the buffer to make room. Perhaps you'll be out of memory at that time? If you want to be sure to be able to process the packets you want to process, it would actually be a very good method to preallocate a buffer of enough size to be able to hold the packets you are going to proces, and then not reallocate it at all.
February 2, 2005, 3:10 AM
Mephisto
[quote author=Adron link=topic=10387.msg97862#msg97862 date=1107313817]
[quote author=Mephisto link=topic=10387.msg97796#msg97796 date=1107288013]
While you are correct, there are certain situations where realloc would be a good thing.  For instance, when inserting data into a buffer that may be of unknown size and you run out of room to insert data, it'd be better IMO to resize the buffer to make room then fail the operation as failing the operation may result in a terminal error (such as failing the Battle.net protocol for a bot).
[/quote]

This sounds like jibberish? Did you read what everyone has been saying? Did you understand that calling "realloc" in many cases will result in a new allocation and copying of data, and that that's what we're talking about? Did anyone at any time suggest to just fail because your fixed size buffer is full?

Also, you shouldn't assume that you will be able to resize the buffer to make room. Perhaps you'll be out of memory at that time? If you want to be sure to be able to process the packets you want to process, it would actually be a very good method to preallocate a buffer of enough size to be able to hold the packets you are going to proces, and then not reallocate it at all.
[/quote]

Edit: Not even going to bother.

I'm sorry if I implied the wrong thing that upsetted you so much.  ::)
February 2, 2005, 6:29 AM
Dyndrilliac
I've decided to use a linked list. Thanks guys.
February 5, 2005, 1:21 AM
Mephisto
[quote author=Dyndrilliac link=topic=10387.msg98254#msg98254 date=1107566486]
I've decided to use a linked list. Thanks guys.
[/quote]

If you're going to be using the structure in the manner of an array a vector may be a more viable solution.  Do a search on std::vector.
February 5, 2005, 1:58 AM

Search