Выходная разница в gcc и turbo C - PullRequest
14 голосов
/ 20 июля 2010

Почему существует разница в выводе, когда код компилируется с использованием двух компиляторов gcc и turbo c.

#include <stdio.h>

int main()
{    
    char *p = "I am a string";
    char *q = "I am a string";

    if(p==q)
    {
        printf("Optimized");
    }
    else{
        printf("Change your compiler");
    }
    return 0;
}

Я получаю "Optimized" на gcc и "Change your compiler" на turbo c.Почему?

Ответы [ 7 ]

33 голосов
/ 20 июля 2010

Ваши вопросы были помечены как C, так и C ++.Поэтому я отвечу за оба языка.

[C]

Из ISO C99 (Section 6.4.5/6)

It is unspecified whether these arrays are distinct provided their elements have the appropriate values.

Это означаетunspecified указывает, указывают ли p и q на один и тот же строковый литерал или нет.В случае gcc они оба указывают на "I am a string" (gcc оптимизирует ваш код), тогда как в turbo c это не так.

Неопределенное поведение: использование неопределенного значения или другое поведениегде настоящий международный стандарт предоставляет две или более возможностей и не предъявляет никаких дополнительных требований, которые будут выбраны в любом случае


[C++]

Из ISO C ++ - 98 (Section 2.13.4/2)

Whether all string literals are distinct(that is, are stored in non overlapping objects) is implementation defined.

В C ++ ваш код вызывает поведение, определяемое реализацией.

Поведение, определяемое реализацией: неуказанное поведение, при котором каждая реализация documents каквыбор сделан


Также см. этот вопрос.

15 голосов
/ 20 июля 2010

Поскольку ваш строковый литерал является константным выражением, то есть вы не должны изменять его с помощью указателя, нет никакой реальной цели дважды хранить его в памяти.Будучи более новым компилятором, gcc объединяет литералы по умолчанию, а Turbo C - нет.Это признак поддержки gcc для более нового стандарта языка, который имеет понятие постоянных данных.

10 голосов
/ 20 июля 2010

Пожалуйста, забудьте ответы в той же строке, что и

"Это потому, что Turbo C настолько ПОЛНОСТЬЮ, и они не могли сделать это ТОГДА, потому что это должно быть БЫСТРО, ноGCC абсолютно новый и RAD, и именно поэтому он делает это! ".

Оба компилятора поддерживают объединение строковых констант в качестве опции.Опция GCC (-fmerge-constants) включена на уровнях оптимизации, а опция Turbo C (-d) по умолчанию отключена.Если вы используете IDE TCC, перейдите на Options|Compiler...|Code Generation.. и отметьте "Duplicate strings merged".

5 голосов
/ 20 июля 2010

Со страницы справочника gcc:

-fmerge-constants

Попытка объединить одинаковые константы (строковые константы и константы с плавающей запятой) в единицах компиляции.

Эта опция используется по умолчанию для оптимизированной компиляции, если ассемблер и компоновщик ее поддерживают.Используйте -fno-merge-constants для запрета этого поведения.

Включено на уровнях -O, -O2, -O3, -Os.

Отсюда вывод.

3 голосов
/ 20 июля 2010

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

1 голос
/ 20 июля 2010

Компилятор может хранить две копии одинаковых литералов, если считает это правильным. Вероятно, цель этой программы - выяснить, так ли это на самом деле.

В старые добрые времена ассемблеры хранили все литералы в литеральном пуле, а исправление литерального пула было признанным (если не утвержденным) методом изменения «констант» в программе.

Если по какой-то причине компилятор разрешит в этом случае *p = 'H';, то могут возникнуть важные различия в поведении.

0 голосов
/ 20 июля 2010

Историческая сноска: Поскольку адреса были меньше, чем числовые константы с плавающей точкой, FORTRAN использовал для обработки констант с плавающей точкой так же, как C обрабатывает строки. Поскольку память драгоценна, идентичные константы будут выделяться в одном и том же пространстве. Кроме того, передача параметров всегда выполнялась по ссылке. Это означало, что если передать числовую константу процедуре, которая изменила свой аргумент, другие вхождения этой «константы» изменили бы значение.

Отсюда старая поговорка: «Переменные не будут, а константы нет».

Кстати, кто-нибудь заметил ошибку в printf в Turbo C 2.0, которая приводила к ошибке при использовании формата, подобного "% 1.1f", для печати чисел, например, 99,99 (вывод 00,0)? Исправлено в 2.01, это напоминает мне об ошибке калькулятора Windows 3.1.

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