Разность выходных данных в 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
. Почему?
Ответы
Ответ 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.