2016-03-30 3 views
1

Я новичок в c. Я пытаюсь читать через Compiler Design In C Голуба. В файле с именем set.c в приложении A к книге автор использует объявление function prototype, как показано ниже.Объявление прототипа функции не скомпилировано

extern int  _addset  P((SET* , int)); 

Это не во время компиляции для меня. Ошибка указана ниже. Я использую gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4.

include/tools/set.h:25:37: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘P’ 
extern void  delset    P((SET*)); 

Когда я изменил декларацию, как показано ниже, код компилируется.

extern int  _addset(SET* , int); 

Так как я не слишком хорошо знаком с c, я не уверен, если я делаю что-то неправильно, изменяя код, как это. Может ли кто-нибудь сказать мне, является ли приведенный выше синтаксис действительным и почему синтаксис из книги не компилируется? Голуб подчеркивает важность использования ANSI C, но на основании того, что я читал, GCC соответствует требованиям ANSI (или более точно ISO).

+1

Похоже, что это зависит от определения макроса для 'P', которого нет, когда вы пытались его скомпилировать. Вам не хватает некоторых из них? Указывает ли книга определение «P»? –

+0

В верхней части файла заголовка нет файлов. Автор обычно является всеобъемлющим с его кодом. Поэтому я предположил, что «P» - это просто владелец места, который не имеет никакого значения. [Compiler Design In C] (http://www.holub.com/software/compilerDesignInC.pdf) Я связываю книгу только в том случае, если вы заинтересованы. Это ни в коем случае не предложение взглянуть на код, который поможет мне. Хотя, это было бы хорошо. 'Set.h' находится на стр. 696. – ShaggyInjun

ответ

3

Проблема заключается в том, что макрос препроцессора P. Конструкция компилятора в C-книге устарела, поэтому автор предоставил обходное решение для аналогичных старых (теперь древних) компиляторов относительно списков аргументов. В книге описано, что она предназначена для:

Макрос P на строках 25 и 28 обрабатывает другую проблему с переносимостью, связанную с ANSI . Многие компиляторы (в том числе многие компиляторы UNIX) не могут обрабатывать прототипы функций. Этот макрос использует механизм, похожий на , на макрос D(), обсужденный ранее, для перевода прототипов в простых деклараций extern, если ANSI не определен. Например, если следующий вход:

int dimitri P((int x, long y)); 

, если ANSI определен, то Р (х) макро оценивает его аргумента и следующие результаты перевода:

int dimitri (int x, long y); 

В противном случае, макро отбрасывает его аргумент и оценивается до(), поэтому будет создано следующее:

int dimitri();

Идея заключается в том, что если у вас есть ANSI-совместимый компилятор, вы должны #define ANSI перед включением заголовочного файла, который определяет P. Затем P оставляет ваш список аргументов один. Но если у вас нет ANSI-совместимого компилятора, вы не определяете ANSI, и препроцессор удаляет список аргументов. P выглядит следующим образом:

#ifdef ANSI 
#define P(x) x 
#else 
#define P(x)() 
#endif 

Я рекомендую удалить P вообще, как вы это сделали. Тем не менее, вы также можете указать #define ANSI или #define P(x) x, если вы хотите иметь возможность копировать и вставлять код из книги как есть.

+0

Ах! Спасибо за подробное объяснение. – ShaggyInjun

-2

Удалить запятая после SET *

Это не должно быть.

+0

Я удалил запятую и скомпилировал ее. Он все еще не работает. Кроме того, этот метод принимает два аргумента, эта запятая разделяет два, нет? Декларация должна быть более похожа на это. '_addset (SET * a, int b);' Но идентификаторы параметров являются необязательными в декларации 'Function Prototype'. Поэтому метод показывает только типы, разделенные запятой. – ShaggyInjun

+2

Этот ответ совершенно неправильный. Не обращайте на это внимания. –

Смежные вопросы