Reduce Prime Sieve Memory Consumption 2
You've posted some code, which shows what you told the computer to do.
And it even has some comments.
Honestly, that's a lot better than the average question.

Then you realize that we aren't going to understand this blob of code, so you use phrases like "I made" and "It uses Euler's Sieve" and "I need the primes up to about two billion".
Look, that's super-useful information, and I'm glad you told me that, but I'm going to suggest that in the future you put information about who wrote the program, the name of the algorithm you use, etc.
into comments embedded in the program:

// pes30.cxx
// prime number generator for Project Euler
// Print all the primes up to 2x10^9.
// 2014-05-08: started by hacatu
// implementation of Euler's sieve (a modified Sieve of Eratosthenes)
// http://en.wikipedia.org/wiki/Euler%27s_sieve
// using wheel factorization with a wheel of size 30 to reduce memory requirements
// http://en.wikipedia.org/wiki/wheel_factorization


So is there some reason not to use http://primesieve.org/ ?
Have you gotten it working without the wheel factorization optimization?
Have you tried looking at only odd prime candidates (wheel of size 2) or a small wheel of size 6 or 12 ?

I am mystified by the 3 lines

bool n[max];//array of whether or not each number is prime (30/8 too big!)
for(big i=0; i&lt;max; ++i)//initialize the array
    n[i]=true;


The "max" is the largest number you want to check for possibly being prime during this run of the program, right?
So that line eats a bunch of memory -- one bool per each number from 0 to max, perhaps 2 million bool values.

I thought you were going to use wheel factorization to reduce memory requirements?

I think you want to replace those 3 lines with something more like the following 2 lines of code:

big blocks_of_30_values = (max/30)+1;
// For example, when max is 38, max/30 gives 1, but we need 2 blocks: 0..29 and 30..59.
// In each block of 30 values under consideration
// (i.e, the block 30..59, the block 60..89, the block 90..119, etc.),
// after using the wheel factorization to eliminate multiples of 2 and 3 and 5,
// there are only 8 potential candidates left in each block.
// So store each block in a single unsigned char:
// and initialize the array to all 1 bits (1=candidate prime, 0=definitely composite)
std::vector&lt;unsigned char&gt; candidatePrime( blocks_of_30_values, 0xFF );


So when max is 2 billion, we only allocate (max/30) = under 70 million chars, or roughly 533 million bits.

It might make your program easier to read if you have named functions for converting a bit in the array to the integer value it represents and vice versa:

// the bit at the n'th bit of the m'th byte of the candidatePrime array
// represents what value?
big the_value( big block_number, int bit_number ){
    const int offset[] = { 1, 7, 11, 13, 17, 19, 23, 29 };
    int this_offset = offset[bit_number];
    return( (30*block_number) + this_offset );
}
// the given integer value n corresponds to
// what (block_number, bit_number) of the candidatePrime array?
// assumes that n is *not* a multiple of 2, 3, or 5.
big block_number( big integer_value ){
    return (integer_value/30);
}
int bit_number( big integer_value ){
    // as long as the integer_value is not a multiple of 2, 3, or 5,
    // this function should never return '9'.
    // translate a value 0..29 into the corresponding bit number 0..7
    const int bit_offset[] = {
        9, 0, 9,  9, 9, 9,
        9, 1, 9,  9, 9, 2,
        9, 3, 9,  9, 9, 4,
        9, 5, 9,  9, 9, 6
        9, 7, 9,  9, 9, 7
    };
    return bit_offset[ integer_value % 30 ];
}