Автоматически удаляющие неиспользуемые локальные переменные от исходного кода C

Вы можете использовать приведенный ниже запрос

Create Table SepvalueTable (Ticket Int, PartNumber char(1))
Insert into SepvalueTable Values (1, 'A'), (1, 'B'),(2, 'C'),(3, 'A'),(3, 'B'),(3, 'C')

SELECT Ticket,
      PartNumber = 
              STUFF ( ( SELECT ' '+InrTab.PartNumber
                  FROM SepvalueTable InrTab
                  WHERE InrTab.Ticket = OutTab.Ticket
                  ORDER BY InrTab.Ticket
                  FOR XML PATH(''),TYPE 
                  ).value('.','VARCHAR(MAX)') 
                 , 1,1,SPACE(0))
FROM SepvalueTable OutTab
GROUP BY OutTab.Ticket;

Вывод такой, как показано ниже

Ticket  PartNumber
------------------
1       A B
2       C
3       A B C

Вы можете найти полную демонстрацию данных в реальном времени Демо здесь

9
задан Nathan Fellman 14 June 2009 в 06:25
поделиться

10 ответов

Поднимите свой уровень предупреждения компилятора, и он должен сказать Вам.

Помещение исходного фрагмента в "f.c":

% gcc -c -Wall f.c
f.c: In function 'fun':
f.c:1: warning: unused variable 'c'
21
ответ дан 4 December 2019 в 06:17
поделиться

Хитрый - необходимо будет проанализировать код C для этого. Как близко результат должен быть? Пример того, что я имею в виду:

int a, /* foo */
    b, /* << the unused one */
    c; /* bar */

Теперь, для людей очевидно, что второй комментарий должен пойти.

Небольшое изменение:

void test(/* in */ int a, /* unused */ int b, /* out */ int* c);

Снова, второй комментарий должен пойти, тот прежде b на этот раз.

В целом Вы хотите проанализировать свой вход, отфильтровать его и испустить все, что это не объявление неиспользуемой переменной. Ваш синтаксический анализатор должен был бы сохранить комментарии и #include операторы, но если Вы не делаете #include заголовков, может быть невозможно распознать объявления (еще больше, если макрос используется для сокрытия объявления). В конце концов, Вам нужны заголовки, чтобы решить если * B (); объявление функции (когда A является типом), или умножение (когда A является переменной),


[редактирование], Кроме того:

Даже если Вы знаете, что переменная неиспользуема, надлежащий способ удалить ее во многом зависит от удаленного контекста. Например, принять

int foo(int a, int b, int c) { return a + b; }

Очевидно, c не использован. Можно ли изменить его на?

int foo(int a, int b) { return a + b; }

Возможно, но не, если &foo хранится интервал a int(*)(int,int,int). И это может произойти где-то в другом месте. Если (и только если), который происходит, необходимо изменить его на

int foo(int a, int b, int /*unused*/ ) { return a + b; }
10
ответ дан 4 December 2019 в 06:17
поделиться

Мой ответ является большим количеством тщательно продуманного комментария к очень полному ответу MSALTER. Я пошел бы вне 'хитрого' и сказал бы, что такой инструмент и невозможен и нецелесообразен.

Если Вы надеетесь просто удалять ссылки на переменную, то Вы могли записать собственный синтаксический анализатор кода, но она должна будет различать функциональный контекст, это находится в таком как

int foo(double a, double b)
{
   b = 10.0;
   return (int) b;
}

int bar(double a, double b)
{
   a = 5.00;
   return (int) a;
}

Любой простой синтаксический анализатор испытал бы затруднения и из-за и из-за 'b', являющийся неиспользуемыми переменными.

Во-вторых, если Вы рассмотрите комментарии, как MSalter имеет, Вы обнаружите, что люди последовательно не комментируют;

double a;
/*a is designed as a dummy variable*/
double b;

/*a is designed as a dummy variable*/
double a;
double b;

double a; /*a is designed as a dummy variable*/
double b;

и т.д.

Таким образом, просто удаление неиспользуемых переменных создаст осиротевшие комментарии, которые возможно более опасны, чем не комментарий вообще.

В конечном счете это - неприлично трудная задача сделать изящно, и Вы исказили бы код независимо. Путем автоматизации процесса Вы сделали бы код хуже.

Наконец, необходимо рассматривать, почему переменные были в коде во-первых, и если они удерживаются от использования, почему они не были удалены, когда все их ссылки были.

5
ответ дан 4 December 2019 в 06:17
поделиться

Почему Вы хотите сделать это? Принятие Вас имеет достойный оптимизирующий компилятор (GCC, Visual Studio и др.), двоичный выход не будет несколько отличаться, удаляете ли Вы 'интервал c' в Вашем исходном примере или нет.

Если это будет примерно очисткой кода, то любой недавний IDE даст Вам быстрые ссылки на исходный код для каждого предупреждения, просто нажать и удалить :)

5
ответ дан 4 December 2019 в 06:17
поделиться

Статические инструменты анализа кода в дополнительном к предупреждению уровня как Paul правильно указали.

1
ответ дан 4 December 2019 в 06:17
поделиться

А также способность показать их посредством предупреждений, компилятор будет обычно оптимизировать их далеко, если какие-либо оптимизации будут включены. Проверка, не ссылаются ли на переменную никогда, довольно тривиальна с точки зрения реализации в компиляторе.

1
ответ дан 4 December 2019 в 06:17
поделиться

Также: шплинт.

Шплинт является инструментом для того, чтобы статически проверить программы C на уязвимости системы обеспечения безопасности и кодировать ошибки. С минимальным усилием Шплинт может использоваться в качестве лучшего линта. Если дополнительное усилие инвестируют, добавляя аннотации к программам, Шплинт может выполнить более сильную проверку, чем может быть сделано каким-либо стандартным линтом.

-1
ответ дан 4 December 2019 в 06:17
поделиться

Вам будет нужен хороший синтаксический анализатор, который сохраняет положение исходного символа маркеров (даже в присутствии препроцессора!). Существуют некоторые инструменты для автоматизированного рефакторинга C/C++, но они далеки от господствующей тенденции.

Я рекомендую Вам проверить Блог Taras. Парень делает некоторые большие автоматизированные рефакторинги кодовой базы Mozilla, как замена-params возвращаемыми значениями. Его основным инструментом для перезаписи кода является Свинина:

Свининой является C++ анализирующий и переписывающий набор инструментальных средств. Ядро Свинины является синтаксическим анализатором C++, который обеспечивает точные позиции символа для запуска и конца каждого узла AST, а также набора макрорасширений, которые содержат любое местоположение. Эта информация позволяет C++ быть автоматически переписанным точным способом.

Из блога:

До сих пор свинина использовалась для “незначительных” вещей как переименование classes&functions, вращение outparameters и исправление prbool ошибки. Кроме того, Свинина оказалась в эксперименте, который включил перезапись почти каждой функции (т.е. генерация 3+MB патч) в Mozilla для использования сборки "мусора" вместо подсчета ссылок.

Это для C++, но это может удовлетворить Вашим потребностям.

0
ответ дан 4 December 2019 в 06:17
поделиться

На одном из плакатов выше написано «невозможно и нецелесообразно». Другой говорит «сложно», и это правильный ответ. Вам понадобится 1) полный синтаксический анализатор C (или любого другого интересующего языка), 2) процедуры вывода, которые понимают язык ссылки на идентификаторы и потоки данных, чтобы определить, что переменная действительно "мертвый", и 3) способность фактически изменять исходный код.

Трудно во всем этом огромная энергия для создания 1) 2) 3). Вы не можете оправдать какую-либо отдельную задачу по очистке. Что можно сделать, так это построить такую ​​инфраструктуру специально с целью окупить его по множеству различных программный анализ и задачи преобразования.

Моя компания предлагает такой инструмент: DMS Software Reengineering Инструментарий. Видеть http://www.semdesigns.com/Products/DMS/DMSToolkit.html У DMS есть интерфейсы качества продукции для многих языков, включая C, C ++, Java и COBOL.

Фактически мы создали автоматизированный "поиск бесполезных объявлений" инструмент для Java, который выполняет две функции: а) перечисляет их все (таким образом получается список!) б) делает копию кода с бесполезными объявлениями удалено. Вы выбираете, какой ответ хотите сохранить: -)

Сделать то же самое для C не составит труда. Мы готовы есть инструмент, который идентифицирует такие мертвые переменные / функции.

Один случай, который мы не упомянули, - это "бесполезный параметр" случае из-за удаления бесполезного параметра у вас есть чтобы найти все вызовы из других модулей, убедитесь, что настройка аргумента не имеет стороны эффект, и вырвите бесполезный аргумент. Фактически у нас есть полные графики всего ПО интересующей системы, и поэтому это также будет возможно.

Так что это просто сложно, и даже не очень сложно. если у вас есть необходимая инфраструктура.

0
ответ дан 4 December 2019 в 06:17
поделиться

You can solve the problem as a text processing problem. There must be a small number of regexp patterns how unused local variables are defined in the source code.

Using a list of unused variable names and the line numbers where they are, You can process the C source code line-by-line. On each line You can iterate over the variable names. On each variable name You can match the patterns one-by-one. After a successful match You know the syntax of the definition, so You know how to delete the unused variable from it.

For example if the source line is: "int a, unused, b;" and the compiler reported "unused" as an unused variable in that line, than the pattern "/, unused,/" will match and You can replace that substring with a single ",".

-1
ответ дан 4 December 2019 в 06:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: