Строгий тест соответствия ISO C

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

Одним из способов достижения хорошей переносимости является кодирование в соответствии с выбранным стандартом, но трудно определить, соответствует ли данная единица перевода строгому стандарту ISO. Например, это может нарушить некоторые пределы перевода, или он может полагаться на поведение undefined без диагностического сообщения из среды компиляции. Я даже не уверен, можно ли проверить строгое соответствие крупных проектов.

Имея это в виду, есть ли какой-либо компилятор, инструмент или метод для проверки строгого соответствия ISO C в соответствии с данным стандартом (например, C89 или C99) единицы перевода?

Любая помощь приветствуется.

Ответ 1

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

void foo(int *p, int *q)
{
    *p = (*q)++;
    ...

который undefined, если p == q. Может ли это произойти, невозможно определить заранее, не решая проблему остановки.

(Отредактировано, чтобы исправить ошибку, о которой сказал кафе. Спасибо, кафе.)

Ответ 2

Не совсем. Стандарт C не устанавливает абсолютные минимальные пределы для единиц перевода, которые должны быть приняты. Таким образом, совершенно точная проверка будет тривиальной для записи, но совершенно бесполезной на практике:

#include <stdio.h>

int main(int argc, char **argv) { 
    int i;
    for (i=1; i<argc; i++)
        fprintf(stderr, "`%s`: Translation limit (potentially) exceeded.\n", argv[i]);
    return 0;
}

Да, это отвергает все, как бы ни было тривиально. Это соответствует стандарту. Как я уже сказал, на практике это бесполезно. К сожалению, вы не можете сделать намного лучше - когда вы решите использовать порт для другой реализации, вы можете столкнуться с некоторым ограничением ресурсов oddball, которого вы никогда не видели раньше, поэтому любой код, который вы пишете (вплоть до включения "hello world" ) может потенциально превышать ограничение ресурсов, несмотря на то, что его разрешают десятки или даже сотни компиляторов в/для гораздо меньших систем.

Изменить:

Почему программа "hello world" не строго соответствует

Во-первых, стоит переформулировать определение "строгого соответствия": "Строго соответствующая программа должна использовать только те функции языка и библиотеки, которые указаны в этом международном стандарте2). Он не должен производить вывод, зависящий от каких-либо неуточненных, undefined или поведение, определяемое реализацией, и не должно превышать минимальный предел реализации."

На самом деле существует ряд причин, по которым "Hello, World" не строго соответствует. Во-первых, как следует из вышеизложенного, минимальные требования к пределам реализации совершенно бессмысленны - хотя должна быть какая-то программа, которая соответствует определенным ограничениям, которые будут приняты, никакая другая программа не должна приниматься, даже если она даже не приближается к любому из этих пределов. Учитывая то, как указано требование, он может поставить вопрос (в лучшем случае) о том, существует ли такая вещь, как программа, которая не превышает минимального предела реализации, поскольку стандарт не определяет минимальные пределы реализации.

Во-вторых, во время первой фазы перевода: "Многобайтовые символы физического исходного файла сопоставляются определенным образом реализации с исходным набором символов..." (§5.1.1.2/1). Поскольку "Привет, мир!" (или любой другой вариант, который вы предпочитаете) предоставляется в виде строкового литерала в исходном файле, он может быть (указан) сопоставлен определенным реализацией с исходным набором символов. Реализация может решить, что (для идиотского примера) строковые литералы будут закодированы в ROT13, и до тех пор, пока этот факт должным образом задокументирован, он совершенно закончен.

В-третьих, вывод обычно записывается через stdout. stdout - текстовый поток. Согласно стандарту: "Символы могут быть добавлены, изменены или удалены на входе и выходе, чтобы соответствовать различным соглашениям для представления текста в среде хоста. Таким образом, не должно быть взаимно однозначного соответствия между символами в потоке и во внешнем представлении". (§7.19.2/2) Таким образом, реализация могла бы (например) выполнить сжатие Хаффмана на выходе (в понедельник, среду или пятницу).

Итак, у нас есть (по крайней мере) три различных точки, в которых вывод из "Hello, World!" зависит от специфических для реализации характеристик - любой из них помешает ему подгонять определение строго соответствующей программы.

Ответ 3

gcc имеет уровни предупреждения, которые будут пытаться связывать различные аспекты соответствия ANSI. Но шляпа только отправная точка.

Ответ 4

Вы можете начать с gcc -std=c99 или gcc -ansi -pedantic.

Ответ 5

Удачи вам в этом. Попытайтесь избежать целых чисел со знаком, потому что:

int f(int x) 
{
 return -x;
}

может вызывать UB.