Arrays of pointers?

Started by
8 comments, last by arm 18 years, 8 months ago
Hi, just wondered if its possible to have an array of pointers and if so whats the correct syntax for declaring them. I want a functon to be able to take in a number of pointers, code below:

// *********************************************************************
// *	Loads Textures into Texture Objects
// *********************************************************************

unsigned int[] TextureHandler :: LoadTextures(char*[] filenames, int numTextures)
{
	BITMAPINFOHEADER[numTextures]	bitmapHeaders;
	unsigned char*[numTextures]		textureInfo;
	unsigned int[numTextures]		textures;

	for(int n = 0; n < numTextures; n++)
	{
		texturesInfo[n] = LoadBitmap(filenames[n], &bitmapHeaders[n]);
		
		glGenTextures(1, &textures[n]);
		glBindTexture(GL_TEXTURE_2D, textures[n]);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, bitmapHeaders[n].biWidth, 
						  bitmapHeaders[n].biHeight, GL_RGB, GL_UNSIGNED_BYTE, textureInfo[n]);
	}

	return(textures);
}
Advertisement
You've got a couple of options when passing an array of pointers. Since arrays and pointers can be used interchangably most of the time in C/C++ you could do this:

void mymethod(char** myarray);

Or you could keep the array syntax and do this:

void mymethod(char* myarray[]);

As for declaring the array in the function, you have:

unsigned char* array[LENGTH];
Alternatively you could pass a vector of strings:


std::vector< std::string > filenames;

This is probably the better way.

ace
oooooooooh shit yeah, was just being a retard with my []placement, but thanks for the reply anyways lol
Also I notice you are returning an array from your function - which has been allocated on the stack. Take care here, since the array could be inadvertantly overwritten without your knowledge.

Its best to allocate the return array at the call site and pass it to your function. That or dynamically allocate the memory.

PS. Like the avatar Ace - "Gigidy Gigidy Gigidy, all right!"
Actually, "int numTextures" is a dynamic variable which can change, and if he is using MinGW (or some other compiler that will do this), it can see that and dynamically allocate the memory. However, if the variable was constant, then it could allocate it on the stack.
(Isn't the stack the memory that is allocated for the program itself?)
Also, you can declare you first variables like this:
BITMAPINFOHEADER bitmapHeader[numTextures];BYTE *textureInfo[numTextures];UINT textures[numTextures];

"BYTE" and "UINT" are defines declared in "windows.h", which means the same thing as what you had up there.
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
Quote:Original post by arm
Also I notice you are returning an array from your function - which has been allocated on the stack. Take care here, since the array could be inadvertantly overwritten without your knowledge.


In fact, this isn't valid - you can't return an array, and returning a pointer is a problem because at that point, the memory for that stack allocation doesn't belong to you any more - it has already been destructed due to the function ending and the variables reaching end of scope.

Quote:Its best to allocate the return array at the call site and pass it to your function. That or dynamically allocate the memory.


Better yet (assuming C++), use an object that will manage the memory allocation such as std::vector - then you don't have to worry about who cleans it up. The vector also knows how many elements it contains, so you don't have to pass that along when you pass one in. Similarly, please please please use std::string for textual data; it will save you lots of headaches.

Oh, and as far as I can tell there's no need to keep around the array of textureInfo or bitmapHeaders; at any given time, you only care about the current one.

vector<unsigned int> TextureHandler :: LoadTextures(const vector<string>& filenames) {  vector<unsigned int> textures;  int count = filenames.size();  for(int n = 0; n < count; ++n) {    BITMAPINFOHEADER currentHeader;    unsigned char* textureInfo = LoadBitmap(filenames[n], &currentHeader);    unsigned int currentTexture;    glGenTextures(1, &currentTexture);    glBindTexture(GL_TEXTURE_2D, currentTexture);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, currentHeader.biWidth, currentHeader.biHeight, GL_RGB, GL_UNSIGNED_BYTE, textureInfo);    // store the actual 'texture'    textures.push_back(currentTexture);  }  return textures;}


... Err... wait... there's a need to store the texture info somewhere isn't there? LoadBitmap() will be allocating memory and storing textures I imagine, and this will just leak all of that away. But then, the original is no better; the textureInfo array disappears at the end, and there is still no way to find the loaded textures after the function call. Better find some place to store them :\
Not all compilers will let you do that (MSVC 2003 certainly doesn't). As far as I was aware only C99 let you declare dynamically sized local arrays. (The OP is using C++ in his example).

As for the compiler (I haven't used MinGW) automatically allocating memory off the heap, I'm very dubious about this being so. If it did this it would introduce the possibility of memory leaks since this memory would need to be explicity freed at some point with a 'delete' statement, unless it was automatically freed by the compiler at the end of the function. In which case, it wouldn't be passable back to the caller, unless there was special handling of this case.

Quote:(Isn't the stack the memory that is allocated for the program itself?)


Yes, allocation of stack memory is handled by the compiler and is used for all locally allocated memory. But, usually, the compiler needs to know the sizes of all locally allocated variables so it can calculate offsets from the stack/base pointer. If you allocate a stack array in C++ and return it, there is the risk that further method calls from the could cause the original data (which is now out of scope) to be overwritten.

arm.

PS, Zahlman, yeah I know the syntax was incorrect I was just trying to explain the principle of not passing out-of-scope data.
Mm, I wasn't trying to correct you, just point out the additional problem with the OP's approach :)

Use of C++ is not actually necessarily evident here - I don't see any use of operator new or any other C++-unique constructs in the OP's example.

To the OP, if you're stuck with C, then std::vector naturally isn't an option. If you knew the size of the arrays you wanted to work with at compile-time, though, you could make things a bit easier on yourself by making a struct to wrap an array of that size.

Otherwise, you'll need to use one of the other tricks mentioned - pass in the 'destination' array (this lets the caller stack-allocate it or heap-allocate it as needed, but complicates the interface), or dynamically allocate a result array and return a pointer to that (this requires that the caller then free the memory when done with it, so the memory management is more complicated overall). In either case, the calling code will have to "remember" how many elements are involved when making use of the result data, so don't be too quick to throw away whatever you passed in for numTextures ;)
Lol its ok Zahlman, I wasn't taking offence. The only hint I got that this could be c++ was the class/namespace scope symbol in the function name (TextureHandler :: LoadTextures). Apart from that though the function body is actually fairly C-neutral. In any case, I think we lost the OP some time ago lol. Hopefully all this may be of use to someone else though.

peace,
arm.

This topic is closed to new replies.

Advertisement