tags:

views:

107

answers:

4

I have this preprocessor directive:

#define INDEXES_PER_SECTOR BYTES_PER_SECTOR / 4

where BYTES_PER_SECTOR is declared in another header file as:

#define BYTES_PER_SECTOR    64

I have this simple math equation that I wrote where after executing I get an assertion error as the value assigned to iTotalSingleIndexes is incorrect.

int iTotalSingleIndexes = (iDataBlocks - 29) / INDEXES_PER_SECTOR;

Now I believe this to be because of the preprocessor directive INDEXES_PER_SECTOR. Upon executing my equation iDataBlocks is 285 which is correct. I have confirmed this with gdb. The problem is that the value that gets assigned to iTotalSingleIndexes is 1 when it ought to be 16. I really have no idea why this is happening.

When I do something like:

int iIndexesInASector = INDEXES_PER_SECTOR;
int iTotalSingleIndexes = (iDataBlocks - 29) / iIndexesInASector;

the correct value gets assigned to iTotalSingleIndexes.

On other notes I use preprocessor directives in other equations and they work just fine so I am even more puzzled.

Any help would be much appreciated.

+7  A: 
#define INDEXES_PER_SECTOR (BYTES_PER_SECTOR / 4)
leppie
+15  A: 

The preprocessor simply performs token replacement - it doesn't evaluate expressions. So your line:

int iTotalSingleIndexes = (iDataBlocks - 29) / INDEXES_PER_SECTOR;

expands to this sequence of tokens:

int iTotalSingleIndexes = ( iDataBlocks - 29 ) / 64 / 4 ;

...which, due to the associativity of the / operator, is then parsed by the compiler as:

int iTotalSingleIndexes = ((iDataBlocks - 29) / 64) / 4;

...which results in the value of 1. As leppie says, you want:

#define INDEXES_PER_SECTOR (BYTES_PER_SECTOR / 4)

This makes INDEXES_PER_SECTOR expand to a complete subexpression.

caf
+3  A: 

Both of the given answers so far are correct,so accept one of them, but I thought I should expand on what they are saying

Number 1 rule of preprocessor macros.

If a macro expands to an expression, always enclose the expansion in parentheses

Number 2 rule of preprocessor macros

Always enclose macro arguments in parentheses where they are used in the expansion

For example, consider the macro below

#define X_PLUS_4(X)    X + 4

foo = 1;
y = 3 * X_PLUS_4(foo + 2) * 4; // naively expect y to be 84

the second line expands to

y = 3 * foo + 2 + 4 * 4;  // y is 13

which is probably not what you want

Applying the rules

#define X_PLUS_4(X)    ((X) + 4)

The use above then becomes

y = 3 * ((foo + 2) + 4) * 4;
JeremyP
+1 because it's necessary to know and follow these rules.
ur
+1  A: 

If you want to accomplish preprocessing-time operations with the preprocessor, you can use the Boost preprocessing library. However, you should REALLY be using const data for this.

const int BytesPerSector = 64;
const int IndexesPerSector = BytesPerSector / 4;

The preprocessor should be reserved for when you have absolutely no other choice. Performing arithmetic at compile-time is easily done with const ints.

DeadMG