Ответ 1
Как мне самому очень интересно узнать ответы на ваш первый вопрос, к сожалению, я не могу дать вам хороший совет здесь.
По крайней мере, вы получите ответ на свой второй вопрос: это несколько полуавтоматический способ, который я использую для ручного добавления отсутствующих или настройки измененных объявлений из файлов заголовков синхронизации.
используйте компилятор с включенными предупреждениями (!), чтобы указать отсутствующие/измененные объявления:
Отрегулируйте объявления
После изменения сигнатуры определения функции gcc
выдаст ошибку, подобную следующей:
-
error: conflicting types for ‘....’
note: previous declaration of ‘....’ was here
Фиксация этого относительно проста, поскольку в сообщении об ошибке уже указаны ссылка на определение и соответствующее объявление.
Поскольку я являюсь пользователем emacs
, я не могу сказать вам, как это делается в vi
, но я уверен, что есть и простой способ автоматического перехода к этим местам.
Все, что нужно сделать, это:
-
перейти к местоположению, скопировать строку
-
переместитесь в локальное место, замените старую строку на копию и добавьте завершающий
;
Отсутствующие объявления
Если с другой стороны была добавлена новая функция без добавления ее прототипа в соответствующий заголовочный файл gcc
, он будет бросать что-то вроде:
-
warning: implicit declaration of function ...
Исправлено это таблицей тегов. Опять же, я не знаю точно, как это обрабатывается в vi
, но я уверен, что есть способ быстро перейти к определению функции, заданному его именем, в предупреждении компилятора.
Рабочий процесс выглядит следующим образом:
-
перейти к функции.... определение, копировать строку
-
перейдите в файл заголовка, вставьте строку и добавьте завершающий
;
Хотя этот метод ничего, кроме элегантного, он оказался для тех случаев, когда я забыл настроить заголовок, чтобы синхронизировать его с исходным файлом, что может быть сделано с помощью нескольких нажатий клавиш.
Сломанный пример
Чтобы продемонстрировать свое приложение на примере здесь, программа minmal, которая нуждается в исправлениях:
/* main.c */
#include "add.h"
int main (int argc, char *argv[]) {
int a=0, b=0;
add (a, b);
sub (a, b);
return 0;
}
Обе функции add
и sub
определены в add.c
, показанной ниже:
/* add.c */
#include "add.h"
int add (int a, int b) {
return a + b;
}
int sub (int a, int b) {
return a - b;
}
Преступник add.h
показывает как несоответствие подписи функции add
, так и отсутствующее объявление функции sub
:
/* add.h */
long add (long a, long b);
Попытка компиляции приведет к:
gcc -Wall main.c add.c
main.c: In function ‘main’:
main.c:7: warning: implicit declaration of function ‘sub’
add.c:3: error: conflicting types for ‘add’
add.h:2: note: previous declaration of ‘add’ was here
Фиксация примера
Отсутствующие объявления
Первая проблема:
-
main.c:7: warning: implicit declaration of function ‘sub’
Это связано с тем, что в add.h
sub
Поиск правильной подписи:
- C-x ` (следующая ошибка) переместится к месту ошибки
- M-. (gtags-find-tag) предложит искать тег
- RET перейдет к определению
sub
, поскольку символ в точке является значением по умолчанию - M-z { (zap-to- char) C-y (yank), чтобы скопировать подпись
Здесь все шаги можно было бы выполнить автоматически с помощью макроса клавиатуры, поскольку никакое вмешательство не требовалось. Следующая часть должна быть сделана вручную:
- откройте "правильный" заголовочный файл
- и перейдите к месту, где должно быть введено объявление
Поскольку выбор "правильного" заголовочного файла и "правильного" местоположения, скорее всего, является вопросом вкуса, в отличие от шагов, предпринятых до сих пор, я не думаю, что здесь возможно много автоматизации.
Наконец, последний шаг - вставить скопированную подпись:
- C-y M-y вставить скопированную подпись
- DEL ; заменить
{
на;
Настройка объявлений
Далее должно быть исправлено несоответствие между объявлением и определением add
.
add.c:3: error: conflicting types for ‘add’
add.h:2: note: previous declaration of ‘add’ was here
Чтобы скопировать новую подпись из определения:
- C-x ` (следующая ошибка) переместится в местоположение определения
- M-z { (zap-to- char) C-y (yank), чтобы скопировать подпись
Чтобы заменить объявление:
- C-x ` (следующая ошибка) переместится в местоположение объявления
- M-z ; (zap-to- char) для удаления старого объявления
- C-y M-y теперь вставьте скопированную подпись
- DEL ; заменить
{
на;
И снова
Так как были добавлены два буфера:
- M-2 M-x burry-buffer должен вернуться в буфер, который был посещен до
Резюме
Как вы можете видеть, но не слишком трудоемкий процесс, постоянно перескакивающий назад и вперед, чтобы исправить недостающие или неправильные объявления, используя этот подход, по-прежнему довольно утомительная задача, я использую его только для исправления деклараций, которые я опечатал или полностью пропустил в первый запуск.
Ручное размещение "правильных" объявлений в заголовке по-прежнему является основным подходом, который я принимаю.
Как изложение API до его реализации, возможно, это не худшая идея IMHO, эта стратегия не должна быть слишком плохим выбором.