C++ - 多个#DEFINE 值导致简单算术失败

C++ - multiple #DEFINE values cause simple arithmetics to fail

我是一个 运行 程序,我在一个大循环中不断递增 "long int"(预期值最大为 10^8)。有问题的 "long int" 初始化为 0。我的控制台打印如下所示:

errorous messages : 400000/5000 = 800000 instances

请注意除法不正确。代码打印上面的行:

std::cout << "errorous messages   : " << total_error << "/" << GRID_SIZE << " = " << (long)((long)total_error / (long)GRID_SIZE) << " instances" << std::endl;

有问题的变量是:

#define BLOCKS      50
#define THREADS     100
#define GRID_SIZE   BLOCKS*THREADS

long int total_error;  <--- incremented in a loop (never decremented, no overflow)

我试过的

我试过将(long)((long)total_error / (long)GRID_SIZE)的除法重铸为(long)(total_error / GRID_SIZE)和其他一些,结果是一样的。


编译信息

 /opt/ohpc/pub/mpi/openmpi-gnu/1.10.6/bin/mpicxx 
-I../../common/inc -I/usr/local/cuda-8.0/include 
-I/export/home/ra2/test_cuda/test_cuda_v0_1/source_code 
-I/export/home/ra2/test_cuda/test_cuda_v0_1/source_code/Utility 
-I/export/home/ra2/test_cuda/test_cuda_v0_1/source_code/Data_objects 
-I/export/home/ra2/test_cuda/test_cuda_v0_1/source_code/cereal   
-std=c++11    -o main.o -c main.cpp

我正在使用 OpenMPI 进行编译。也有 CUDA,但这是 main.cpp 并且没有 CUDA 代码。


问题

我错过了什么?为什么这么简单的操作我会得到错误的结果?


问题的理由

#define GRID_SIZE   BLOCKS*THREADS

应该是

#define GRID_SIZE   (BLOCKS*THREADS)

或更好

const int GRID_SIZE = BLOCKS*THREADS; 

因为 #defines 只是文本替换,所以你的

(long)((long)total_error / (long)GRID_SIZE)

扩展为

(long)((long)total_error / (long)BLOCKS*THREADS)

并且,因为除法 (/) 和乘法 (*) 运算符具有相同的优先级,所以整个表达式从左到右求值,实际上等于:

400000 / 50 * 100 = 8000 * 100 = 800000

考虑在括号中 #define 秒内完成的换行计算,以防止出现此类问题:

#define GRID_SIZE   (BLOCKS*THREADS)