• Welcome to Valhalla Legends Archive.
 

Question Regarding Arrays

Started by Dyndrilliac, January 31, 2005, 05:18 PM

Previous topic - Next topic

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)"
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

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.

Dyndrilliac

Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

Dyndrilliac

#3
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:

#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;
}
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

MyndFyre

#4
Quote from: Dyndrilliac on January 31, 2005, 06:19 PM
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?
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:

char *pszString = (char*)malloc(5 * sizeof(char));

In the case of char, it IS the number of indices; however, for larger data types, such as DWORD:

typedef unsigned long int DWORD;

DWORD *pDwordArray = (DWORD*)malloc(5 * sizeof(DWORD));


Quote from: Dyndrilliac on January 31, 2005, 06:19 PM
Also, do I declare the array without any indexes then use malloc on it? Example:

#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);
   }
}

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:


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;
}

Recall order of operations; i*sizeof(DWORD) comes first, and so you're getting an offset into the memory that was allocated at pDwordArray.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

UserLoser.

Correct me if I'm wrong, but isn't malloc supposed to be for C, while new is for C++?

Newby

Mephisto stated that, IIRC.

Quote from: Mephisto on January 31, 2005, 05:21 PM
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.
- Newby

Quote[17:32:45] * xar sets mode: -oooooooooo algorithm ban chris cipher newby stdio TehUser tnarongi|away vursed warz
[17:32:54] * xar sets mode: +o newby
[17:32:58] <xar> new rule
[17:33:02] <xar> me and newby rule all

Quote<TehUser> Man, I can't get Xorg to work properly.  This sucks.
<torque> you should probably kill yourself
<TehUser> I think I will.  Thanks, torque.

MyndFyre

#7
Quote from: UserLoser on January 31, 2005, 07:01 PM
Correct me if I'm wrong, but isn't malloc supposed to be for C, while new is for C++?

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:

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.
}

However:

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
}
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Mephisto

#8
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.

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?

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
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

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.

Adron

Quote from: Dyndrilliac on February 01, 2005, 09:28 AM
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.

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.

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: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
};
Quote from: Edsger W. DijkstraIt is practically impossible to teach good programming to students that have had a prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.

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?)