我不明白如何允许 #define LEFT (phnum + 4( % N 因为甚至没有定义 phnum。
#define N 5
#define LEFT (phnum + 4) % N
#define RIGHT (phnum + 1) % N
int state[N];
int phil[N] = { 0, 1, 2, 3, 4 };
sem_t mutex;
sem_t S[N];
void test(int phnum)
{
if (state[phnum] == HUNGRY
&& state[LEFT] != EATING
&& state[RIGHT] != EATING) {
// state that eating
state[phnum] = EATING;
sleep(2);
}
语句#define LEFT (phnum + 4) % N
定义了一个名为LEFT
的"宏",其替换列表为(phnum + 4) % N
。编译器不需要知道有关替换列表中的名称的任何信息;它只是记住它。
稍后在源代码中看到LEFT
时,编译器会将其替换为替换列表(phnum + 4) % N
。因此,state[LEFT] != EATING
变得state[(phnum + 4) % N] != EATING
。
替换后,编译器根据它看到的名称来解释名称。
从概念上讲,所有"预处理器"操作,例如定义宏,用替换列表替换它们,以及处理#if
和其他标有#
的语句,都发生在程序的语义分析之前。它之所以被称为"预处理",是因为从历史上看,它是在编译前的单独处理阶段完成的,即使使用单独的程序也是如此。在现代编译器中,预处理器操作可能与编译的其余部分交错,但结果是相同的。
#define LEFT (phnum + 4) % N
定义宏。宏替换由预处理器在编译器实际编译代码之前执行。换句话说,在编译器处理代码之前,state[LEFT]
会被state[(phnum + 4) % N]
替换。
如果您使用的是 GCC:传递-E
参数会告诉 GCC 在预处理阶段后停止,以便您可以检查输出。请注意,预处理器还负责#include
行,因此您可能需要在输出中搜索感兴趣的部分。