Подтвердить что ты не робот

Разность выходных данных в gcc и turbo C

Почему существует разница в выходе, полученном при компиляции кода с использованием двух компиляторов 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. Почему?

4b9b3361

Ответ 1

Ваши вопросы отмечены как 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 С++ - 98 (Section 2.13.4/2)

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

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

Реализация, определяемая поведением: Неопределенное поведение, когда каждая реализация documents, как делается выбор


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

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

На странице руководства gcc:

-fmerge-константа

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

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

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

Следовательно, выход.

Ответ 5

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

Ответ 6

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

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

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

Ответ 7

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

Следовательно, старая поговорка: "Переменные не будут, константы - нет".

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