View Single Post
Old September 22, 2009, 20:13   #5
zaimoni
Knight
 
zaimoni's Avatar
 
Join Date: Apr 2007
Posts: 590
zaimoni is on a distinguished road
Quote:
Originally Posted by Sirridan View Post
Actually, I ran this code segment on the same basic array, and N_ELEMENTS was returning 12 for resists as it should...
Which is completely irrelevant to the original bug.

Code:
#include <stdio.h>

#define N_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))

/* ... */

void main()
{
	static const unsigned int ego_resists[] =
	{
	        TR1_RES_POIS,
	        TR1_RES_FEAR,
	        TR1_RES_LITE,
	        TR1_RES_DARK,
	        TR1_RES_BLIND,
	        TR1_RES_CONFU,
	        TR1_RES_SOUND,
	        TR1_RES_SHARD,
	        TR1_RES_NEXUS,
	        TR1_RES_NETHR,
	        TR1_RES_CHAOS,
	        TR1_RES_DISEN,
	};
	printf("%d\n",N_ELEMENTS(ego_resists));
	printf("done\n");
}
The extent of the ego_resists array is calculated at compile time, and happens to be 12. While in the original code:
Code:
u32b get_new_attr(u32b flags, const u32b attrs[])
{
	size_t i;
	int options = 0;
	u32b flag = 0;
	for (i = 0; i < N_ELEMENTS(attrs); i++)
	{
		/* skip this one if the flag is already present */
		if (flags & attrs[i]) continue;

		/* each time we find a new possible option, we have a 1-in-N chance of
		 * choosing it and an (N-1)-in-N chance of keeping a previous one */
		if (one_in_(++options)) flag = attrs[i];
	}
	return flag;
}
The parameter const u32b attrs[] is decayed at compile time to const u32b *attrs . The language standards (C90/C99/C1X) require 1==N_ELEMENTS(attrs).

The most direct fix is
Code:
u32b get_new_attr(u32b flags, const u32b *attrs, u32b attrs_size)
{
	size_t i;
	int options = 0;
	u32b flag = 0;
	for (i = 0; i < attrs_size; i++)
	{
		/* skip this one if the flag is already present */
		if (flags & attrs[i]) continue;

		/* each time we find a new possible option, we have a 1-in-N chance of
		 * choosing it and an (N-1)-in-N chance of keeping a previous one */
		if (one_in_(++options)) flag = attrs[i];
	}
	return flag;
}
and use N_ELEMENTS on the array where it actually is an array.
__________________
Zaiband: end the "I shouldn't have survived that" experience. V3.0.6 fork on Hg.
Zaiband 3.0.10 ETA Mar. 7 2011 (Yes, schedule slipped. Latest testing indicates not enough assert() calls to allow release.)
Z.C++: pre-alpha C/C++ compiler system (usable preprocessor). Also on Hg. Z.C++ 0.0.10 ETA December 31 2011
zaimoni is offline   Reply With Quote