Как ты понимаешь, define обрабатывается препроцессором, т.е. вместо макроса на стадии компиляции будет помещено твое число. const же помещает число в секцию text (т.е. если это, например, микроконтроллер, его потом можно будет изменять, перезаписывая флеш).
На ПК разница лишь в том, что define не дает константе тип, что в некоторых случаях может вызывать проблемы.
define это директива, если написать #define X Y то компилятор просто заменит во всем тексте символы Х на Y. А что такое X и Y это тебе решать. Это не переменная.
const означает невозможность изменения, но может быть проинициализирован разными значениями. const нельзя использовать для задания размера статического массива например
Это вообще черновик, писал когда был временно безработный, сейчас времени не особо, занят другим пет-проектом. Просто книга - побочка над тьюринг полным macro-based с89-complied проектом. Т.е. весь матан на макросах без ограничений которые есть в бусте, без самого boost и c89-complied.
echo 'const int size = 10; int main(int argc, char *argv[]) { }' | gcc -x c -S - -o -
А почему тогда в .rodata, если не константные?
Данные то считаются константными, но язык не рассматривает значения переменных как константные выражения. Константы могут быть extern и, видимо, чтобы быть последовательными, все константы считаются условно изменяемыми (может в Rational описывается это решение, не смотрел).
Константы могут быть extern и, видимо, чтобы быть последовательными, все константы считаются условно изменяемыми (может в Rational описывается это решение, не смотрел).
На сколько я понимаю, скорее дело в том, что значение может быть в другой единице трансляции.
Если в a.c задано const int a = 10;, а в b.c extern const int a; int b[a];, то при компиляции b.c компилятор не будет знать, сколько выделять под b.
Это зависит от компилятора. Я цитатну кусочек уже сброшенной главы:
#include <stdio.h>
const int VALUE = 100; 4
int main()
{
printf("At first I was %d\n", VALUE);
*(int *)&VALUE = 101;
printf("But then I was like %d\n", VALUE);
return 0;
}
Этот код является типичным случаем UB1. Он должен сработать на Borland C++ и Turbo C++ компиляторах, упасть из-за segmentation fault на GCC, попытаться перетереть FLASH на эмбеддед системах, попытаться перетереть .text секцию на MSVC и так далее. Даже GCC на разных уровнях оптимизации выдает разное поведение:
Без этого костыля ты никак в rodata данные не засунешь! И будут они в оперативке болтаться, хотя нафиг это не нужно. А const позволяет легко и просто жирные таблицы (хоть по 16кБ) шрифтов воткнуть в микроконтроллеры с оперативкой в 2кБ!!!
Я знаю, что так можно попытаться сделать и что это UB вне зависимости, в .rodata оно или где. Вопрос был в том, почему оно с точки зрения языка не константно, а не где будет размещено.
Потому что в разных реализациях дело может обстоять по разному. То что тебе конкретный компилятор под конкретную платформу сделал таким образом, не значит, что во всех остальных случаях будет также.
Я знаю. Константу можно выкинуть вообще, с -O{2,3} gcc так и сделает, скорее всего. Оставит её в операндах инструкций. Но стандарт учитывает-то не реализации, а самого себя, про что мне и ответили.