Expanding the size of an array in C?

Started by
15 comments, last by LessBread 17 years, 5 months ago
if you want to do it the fun way you can use a double pointer, allowing you to use it how you currently are ( Map[ x ][ y ] )


setup the map how you are plus the current width and height...
unsigned int MapWidth = 0, MapHeight = 0;struct MapFormat ** Map = 0; // except now we have to malloc this array!



then to resize the map you can use this function:
void SetMapSize( unsigned int _Width, unsigned int _Height ){	unsigned int i;	if( Map == 0 )	{		// create original memory		Map = ( void * )malloc( sizeof( void * ) * _Width );		for( i = 0; i < _Width; i++ )			Map = malloc( <span class="cpp-keyword">sizeof</span>( <span class="cpp-keyword">struct</span> MapFormat ) * _Height );<br>	}<br>	<span class="cpp-keyword">else</span><br>	{<br>		<span class="cpp-comment">// chop off the extra width if the width is set smaller!</span><br>		<span class="cpp-keyword">for</span>( i = _Width; i &lt; MapWidth; i++ )<br>			free( Map );<br><br>		<span class="cpp-comment">// resize width of the map</span><br>		Map = realloc( Map, <span class="cpp-keyword">sizeof</span>( <span class="cpp-keyword">void</span> * ) * _Width );<br>		<br>		<span class="cpp-comment">// add extra width if the width was set larger!</span><br>		<span class="cpp-keyword">for</span>( i = MapWidth; i &lt; _Width; i++ )<br>			Map = malloc( <span class="cpp-keyword">sizeof</span>( <span class="cpp-keyword">struct</span> MapFormat ) * _Height );<br>		<br>		<span class="cpp-comment">// resize the old height</span><br>		<span class="cpp-keyword">if</span>( _Height != MapHeight )<br>			<span class="cpp-keyword">for</span>( i = <span class="cpp-number">0</span>; i &lt; ( _Width &lt; MapWidth ? _Width : MapWidth ); i++ )<br>				Map = realloc( Map, <span class="cpp-keyword">sizeof</span>( <span class="cpp-keyword">struct</span> MapFormat ) * _Height );<br>	}<br>	MapWidth = _Width;<br>	MapHeight = _Height;<br>}<br><br></pre></div><!–ENDSCRIPT–><br><br><br>then when you're ending your program don't forget to destroy the allocated memory!!<br><br><!–STARTSCRIPT–><!–source lang="c"–><div class="source"><pre><br><span class="cpp-keyword">void</span> DestroyMap()<br>{<br>	<span class="cpp-keyword">unsigned</span> <span class="cpp-keyword">int</span> i;<br>	<span class="cpp-keyword">for</span>( i = <span class="cpp-number">0</span>; i &lt; MapWidth; i++ )<br>		free( Map );<br>	free( Map );<br>	Map = <span class="cpp-number">0</span>;<br>}<br><br></pre></div><!–ENDSCRIPT–><br><br>
see you in heaven
Advertisement

.

Quote:Original post by Kada2k6
Quote:Original post by erissian
It looks like you want to load a map during runtime. Why not include a file header that declares the size of the map, and then allocate however much you need?

Yupp, you read my mind! But I was under the impression that you can't declare variables further down a program or function?

void LoadMap() {
open the file
read the header and get the width & height of the map
declare the struct MapFormat array <- not possible...?
continue loading map
}


Hmm.... So all the logic goes in the LoadMap() function [wink]? What are you going to do with the map if it will disappear once the function ends?

EDIT: And also - IIRC Ansi C doesn't allow variable-sized stack arrays. That is, this would be illegal (even though some compilers probably allow it):
int a = 34;int b = 7;int map[a]; // IIRC isn't allowed

I simply suggest you use the free-store.
Quote:Original post by agi_shi
EDIT: And also - IIRC Ansi C doesn't allow variable-sized stack arrays. That is, this would be illegal (even though some compilers probably allow it):
*** Source Snippet Removed ***
I simply suggest you use the free-store.


C89 doesn't allow it but C99 does. C99 allows for variable length arrays on the stack, but "If an identifier is declared to be an object with static storage duration, it shall not have a variable length array type." (6.7.5.2 Array declarators) Many compilers also provide an implementation of alloca for dynamic stack allocations even though it is non-standard.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by Kada2k6
Thank you for your quick answers! I guess the solution I was looking for was similiar to the one TheUnbeliever provided, so thanks a lot for that. I will try it out right away. Thanks to all your others as well for explaining!


The wrapper proposed by hplus is far more sane. realloc() has no way of knowing that your array "is 2-dimensional". It will copy the old data across, but the net result is that it isn't where you want it to be - instead it gets strung out across the first couple of "rows" of the larger array. Plus, you still have to do indexing calculations, so you may as well wrap up the size information in a struct together with the array, and may as well make a function to wrap up the index calculation.

But do you *really* need to use *C*, in the year 2006?

Quote:Original post by agi_shi
EDIT: And also - IIRC Ansi C doesn't allow variable-sized stack arrays. That is, this would be illegal (even though some compilers probably allow it):


It's not a matter of the compiler, but the language standard. C99 is a fair bit different (as it should be) from C90.
Quote:Original post by Zahlman
Quote:Original post by Kada2k6
Thank you for your quick answers! I guess the solution I was looking for was similiar to the one TheUnbeliever provided, so thanks a lot for that. I will try it out right away. Thanks to all your others as well for explaining!


The wrapper proposed by hplus is far more sane. realloc() has no way of knowing that your array "is 2-dimensional". It will copy the old data across, but the net result is that it isn't where you want it to be - instead it gets strung out across the first couple of "rows" of the larger array. Plus, you still have to do indexing calculations, so you may as well wrap up the size information in a struct together with the array, and may as well make a function to wrap up the index calculation.


Very true, I didn't think of quite how messy that could get (well, not that hplus0603's wrapper is messy). However, I was making the assumption that if he's loading a new map, the contents of the old one don't matter - so the indexing can be done as normal. Then again, if that's true then you're as well freeing the old Map pointer and allocating a new, appropriately sized, chunk of memory.
[TheUnbeliever]
You are gonna hate this answer but in fact it is a completely valid solution.

Just analyze the maximum map size and reserve that space. Then Use the ammount you need from that space. That means:
char map[256][256];

And then use two variables:
int mapSizeX = 16, mapSizeY = 16;

Before you start flaming this answer shouting things like "You are wasting memory!!!!"... and all that just think a moment... How much memory will you really waste? 1MB? Thats too little for a compoter these days and the advantages are greater.

Searching a value in an array is faster than searching in a couple of vectors (slightly faster but you will access it time and time again). Also clearing the array is way faster as you can clear it in a single call. Thats useful for some algortithms like A*.

Computer science is always a battle between fast code and memory efficient code. Fast code usually uses a lot of memory. Memory efficient is slower. I'm not saying at all you must always do everything this way and that memory allocation is useless. I'm just saying that some data structures require more attention to memory management while others, like a map definition, won't hit your memory and your performace can be improved (and your code will be easier) by just 'wasting' some non critical memory.

Luck!
Guimo


Quote:
Before you start flaming this answer shouting things like "You are wasting memory!!!!"... and all that just think a moment... How much memory will you really waste? 1MB? Thats too little for a compoter these days and the advantages are greater.


It's not the memory "waste" that is a concern, it the frailty of such a solution in the presence of maintainence and, even worse, change.
Quote:Original post by Guimo
How much memory will you really waste? 1MB? Thats too little for a compoter these days and the advantages are greater.


That's fine for heap memory or unitialized data, but it's more than enough to blow the stack or bloat the executable.

"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man

This topic is closed to new replies.

Advertisement