C минимальное стандартное требование

Страница будет перезагружена, если вы не хотите использовать javascript

1
задан user2162550 18 January 2019 в 12:41
поделиться

2 ответа

  1. Да, реализация C (не просто компилятор - включены стандартная библиотека, поддержка ссылок и поддержки времени выполнения и / или все, что используется для реализации C), которая производит такое же наблюдаемое поведение 1 , как и соответствующая абстрактная машина. Все остальные требования и параграфы в стандарте не являются просто дополнительными. Они определяют поведение абстрактной машины, поэтому они способствуют описанию того, каким должно быть наблюдаемое поведение.

  2. Да, программа, которая не имеет наблюдаемого поведения, может быть оптимизирована для программы, которая просто возвращает. Обратите внимание, что стандарт на самом деле не включает статус выхода в наблюдаемом поведении , поэтому xor eax, eax технически не требуется. Тем не менее, это скорее всего случайный дефект в стандарте, а не намерение.

Примечания

1 Поведение программ - не единственное, что требуется в спецификации. Реализации также должны документировать, например, различное поведение, определяемое реализацией. Таким образом, эта гипотетическая реализация C, которая ведет себя идентично некоторой абстрактной машине, также должна включать в себя необходимую документацию.

0
ответ дан Eric Postpischil 18 January 2019 в 12:41
поделиться
1112 Да, вы правы. Компилятор может делать то, что он хочет, при условии, что наблюдаемое поведение является тем же, что и абстрактная машина, которую может создать . Но это не драматично само по себе: почему мы заботимся о том, чего нельзя наблюдать? В этом смысл оптимизации компиляторов.

Пример:

int main() {
    int a;
    for (int i=INT_MAX; i>=0; i--) {
        a = i;
    }
    printf("%d\n", a);
    return 0;
}

Единственное наблюдаемое поведение это то, что он будет печатать 0 за один раз. Таким образом, компилятор может оптимизировать цикл таким образом:

int main() {
    printf("%d\n", 0);
    return 0;
}

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

ИМХО, самый драматичный побочный эффект, если компилятору разрешено предполагать, что в программе не может быть неопределенного поведения.

Второй пример:

int main() {
    struct {
        int a[16];
        int b[16];
    } s;

    for (i=0; i<16; i++) {
        s.a[i] = i;
        s.b[i] = 2 * i;
    }
    for (i=0; i<32; i++) {
        printf(" %d", s.a[i]);      // UB array access past upper bound
    }
    printf("\n");
    return 0;
}

Наивный компилятор должен отображать все числа от 0 до 31, потому что мы знаем, что массивы s.a и s.b должны быть смежными, а арифметика указателей должна давать &(s.b[0]) == &(s.a[16]) , Но оптимизирующий компилятор может заметить, что значения s.b никогда не используются в наблюдаемом поведении, если не задействован ни один UB, и он свободен для оптимизации доступа к массиву s.b и даже для оптимизации члена b. Здесь следует ожидать аварийных или случайных значений ... Хуже того, действительно умный компилятор может заметить, что в цикле печати есть прошлые связанные обращения. С этого момента поведение программы не определено, и компилятор может, например, остановить цикл после печати 16-го значения. Нет ошибок, но напечатано только 16 значений ...

0
ответ дан Serge Ballesta 18 January 2019 в 12:41
поделиться
Другие вопросы по тегам:

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