Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Доброго времени суток. Насколько я понял из прочтённого в литературе по C - размер массивов должен назначаться константным значением, т.е. это может быть либо целочисленная переменная, объявленная через #define, либо целочисленная переменная, объявленная как const, либо значение из enum, или же, как последний вариант - непосредственно указывается число. Сейчас я прочитал такую информацию: Брайан Керниган Определяйте числа как переменные-константы, а не как макросы. ... В языке C тоже есть ключевое слово const , но такие константы не могут служить границами массивов, поэтому в C следует отдавать предпочтение перечислимому типу ( enum ). ... Полагаю, что под "границей" массива подразумевается его размер. Я не понял, почему константы не могут служить границами массивов? Следующий код успешно компилируется, хотя границы массива создаются как на основе константы, так и на основе enum-значения: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. Скорее всего, я что-то не верно понял... Тогда что именно? С уважением, Андрей __________________ Британские "учёные" - фундаментальный подход к разной фигне... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2013, 22:05 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
CompositumСкорее всего, я что-то не верно понял... Тогда что именно? А Вы чем занимаетесь? Случайно не учите ли Вы С++ начиная с С? В книгах могут быть ошибки. Но Кернигана мы все знаем и чтим. Суть вещей очень проста. Размер массива должен быть однозначно определен в момент компиляции приложения. Т.е. это такие варианты: константа, enum (перечисление), define, число (литерал). Правильный вариант только один: константа (но есть исключения). Gcc и WinAPI позволяют создавать локальные массивы заранее неизвестной длинны. Но это никчемный путь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2013, 23:13 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
petrav Суть вещей очень проста. Размер массива должен быть однозначно определен в момент компиляции приложения. Т.е. это такие варианты: константа, enum (перечисление), define, число (литерал). Правильный вариант только один: константа (но есть исключения). А чем enum то не угодил? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2013, 23:41 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
petravА Вы чем занимаетесь? Случайно не учите ли Вы С++ начиная с С? Нет, я именно C и учу (ISO/IEC 9899:1990, если быть более точным). K&R уже прочитал, попутно выполняю упражнения из книги. Сейчас читаю книгу "Практика программирования", написанную указанным мною выше автором. petravСуть вещей очень проста. Размер массива должен быть однозначно определен в момент компиляции приложения. Это я знаю. petravТ.е. это такие варианты: константа, enum (перечисление), define, число (литерал). Это я тоже знаю, но выше указанная мною цитата сбивает с толку... petravПравильный вариант только один: константа (но есть исключения). Понимаю это, но опять же - какая-то несостыковка с указанным мною выше текстом... petravGcc и WinAPI позволяют создавать локальные массивы заранее неизвестной длинны. Но это никчемный путь. При компиляции я указываю опцию -std=c90, сообщая тем самым, что исходный код следует проверять на полное соответствие стандарту C90 (т.е. ISO/IEC 9899:1990). В соответствии с указанным мною стандартом размер массива должен задаваться константой (в C11 размер можно назначать динамически, но не в C90). Поскольку меня интересует написание кода в соответствии со стандартом, то дополнительные возможности от Gcc и WinAPI пока игнорирую. @ petrav Вы мне вроде и написали, но... Ответа на мой вопрос в вашем сообщении не содержится. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2013, 23:42 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
enum не угодил?petrav Суть вещей очень проста. Размер массива должен быть однозначно определен в момент компиляции приложения. Т.е. это такие варианты: константа, enum (перечисление), define, число (литерал). Правильный вариант только один: константа (но есть исключения). А чем enum то не угодил? Можно купить мерседес (черный!:) и поехать на нем траву косить. Каждой вещи свое назначение. Использование перечислений по не прямой надобности родилось тогда, когда в стандарте не было такого: Код: plaintext 1. 2. 3. 4. Разве я не прав? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2013, 23:55 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Compositum, Извините =) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.03.2013, 23:55 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
petravКаждой вещи свое назначение. Использование перечислений по не прямой надобности родилось тогда, когда в стандарте не было такого: Код: plaintext 1. 2. 3. 4. Разве я не прав? В C этого до сих пор нет. Прошу не путать C с C++. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 00:00 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
petravenum не угодил?пропущено... А чем enum то не угодил? Можно купить мерседес (черный!:) и поехать на нем траву косить. Каждой вещи свое назначение. Использование перечислений по не прямой надобности родилось тогда, когда в стандарте не было такого: Код: plaintext 1. 2. 3. 4. Разве я не прав? Для C++ я бы сказал пока не появилось constexpr. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 00:25 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
constexpr, Да причем тут constexpr? Enum - это по сути перечисление некоторых логических состояний объекта внимания: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Когда не было инлайн инициализации статических констант -- их заменяли enum-ами. Потому что это удобно. Когда стат. константы появились -- перечисления обрели свое истинное назначение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 00:40 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
В С ключевое слово const означает что данную переменную вы (тот модуль который видит это объявление) не можете изменять,но это не значит что в других модулях ее нельзя изменить. Поэтому такие переменые нельзя изпользовать как границы массива - это не константы, а константные ссылки к переменным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 01:08 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyПоэтому такие переменые нельзя изпользовать как границы массива - это не константы, а константные ссылки к переменным. Но ведь границы массива указываются целыми числами, которые передаются не по ссылке, а по значению. И ещё такой момент: если в C переменная объявлена как const, то разве компилятор не подставляет её непосредственное значение вместо имени этой переменной во всём коде при компиляции (за исключением const аргументов функции)? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 08:59 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
CompositumИ ещё такой момент: если в C переменная объявлена как const, то разве компилятор не подставляет её непосредственное значение вместо имени этой переменной во всём коде при компиляции (за исключением const аргументов функции)? Полистал K&R, и в начале 2-й главы прочёл это (причём ранее ведь уже читал это): Chapter 2 - Types, Operators and ExpressionsThe ANSI standard has made many small changes and additions to basic types and expressions. ... Objects may be declared const, which prevents them from being changed. Т.е. замена не происходит, а вместо этого при компиляции выполняется лишь проверка на то, чтобы в коде не присутствовало изменение переменной, помеченной как const. Но ведь когда я компилирую код с опцией -std=c90, то ошибок не получаю, несмотря на то, что в качестве размера массива указываю const переменную. Т.е. может быть в C90 разрешили указывать переменные, помеченные как const, а автор книги писал о C89? Обратите внимание на следующий код: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. В этом коде я назначаю константе x вычисляемое значение. В C# такой фокус бы не прошёл, но в C#, при компиляции в CIL, насколько я помню, в исходном коде все const переменные заменяются их значениями. Затем для массива m я в качестве размера подставляю функцию, а не константное значение. Ожидаю, что в этом месте получу ошибку компиляции (особенно с учётом того, что при компиляции указана опция -std=c90), однако код компилируется без проблем. Честно говоря, я в замешательстве... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 10:05 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
CompositumAnatoly MoskovskyПоэтому такие переменые нельзя изпользовать как границы массива - это не константы, а константные ссылки к переменным. Но ведь границы массива указываются целыми числами, которые передаются не по ссылке, а по значению.Во первых, у тебя кривой перевод учебника. В С нету "границ массива", там есть только "размер статического массива" и "размер динамически выделенного куска памяти". Статический массив определяется на этапе компиляции, динамический в рантайме. Размер для обоих может быть только целым. Compositum И ещё такой момент: если в C переменная объявлена как const, то разве компилятор не подставляет её непосредственное значение вместо имени этой переменной во всём коде при компиляции (за исключением const аргументов функции)?Нет, не подставляет. Если ты сделал const переменную, то она будет создана в сегменте "только для чтения" и ты сможешь брать указатель на нее и читать ее (напрямую или через указатель). Но не сможешь изменять, иначе segmentation fault получишь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 10:22 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
White OwlCompositum И ещё такой момент: если в C переменная объявлена как const, то разве компилятор не подставляет её непосредственное значение вместо имени этой переменной во всём коде при компиляции (за исключением const аргументов функции)?Нет, не подставляет. Если ты сделал const переменную, то она будет создана в сегменте "только для чтения" и ты сможешь брать указатель на нее и читать ее (напрямую или через указатель). Но не сможешь изменять, иначе segmentation fault получишь. Выше я уже отписался о том, что ответ на данный вопрос мною уже найден. White OwlСтатический массив определяется на этапе компиляции, динамический в рантайме. Размер для обоих может быть только целым. Это мне известно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 10:27 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Compositum, White Owl, Не следует мешать все в кучу. Так вот. Переменые (в широком смысле, включая константы) можно объявить со статическим размещением в сегменте данных (к ним относятся глобальные и статические переменные) и с автоматическим размещением в стеке (локальные нестатические). Рассмотрим эти два варианта в применении к массивам и их размерам: 1) Если мы объявили статический массив Код: plaintext 1. то max там может быть только литеральной константой или enum. Вот это не является ни тем ни другим: Код: plaintext 1. Как я уже выше писал, в C (но не в C++) const не означает что это константа, а означает что следующий за ним код не может модифицировать значение, а из других модулей оно вполне может модифицироваться. Т.е. корректный пример демонстрирующий этот вариант такой: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 2) Теперь расмотрим массив объявленный внутри функции (с автоматической памятью). Здесь в С (и опять же не в С++) действуют совсем другие правила чем для статических массивов. Размер локального массива вычисляется не при компиляции, а при входе в функцию при ее выполнении (я сейчас не рассматриваю оптимизации). А поэтому в качестве размера массива там может быть любое целое выражение допустимое в С в том месте. Код: plaintext 1. 2. 3. 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 17:14 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyКак я уже выше писал, в C (но не в C++) const не означает что это константа, а означает что следующий за ним код не может модифицировать значение, а из других модулей оно вполне может модифицироваться.Не может. Компилятор это пропустит, но программа упадет. Код: plaintext 1. 2. Код: plaintext 1. 2. 3. 4. 5. Компилируется без проблем, а в рантайме мрет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 18:24 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
White OwlAnatoly MoskovskyКак я уже выше писал, в C (но не в C++) const не означает что это константа, а означает что следующий за ним код не может модифицировать значение, а из других модулей оно вполне может модифицироваться.Не может. Компилятор это пропустит, но программа упадет.И вообще, это один из способов стрельбы по своей ноге. Объяви переменную const а потом сделай присваивание ей через приведение типов. С глобальными переменными таким образом ты убьешь программу, а с локальным const выживет. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 18:28 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
White Owl, Суть моего объяснения выше не в том что есть возможность менять переменные const, а в том что с точки зрения языка const это не константа, а значит не может быть размером массива, там где разрешены только константы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 19:39 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
А насчет корректности модификации const - в языке когда делали эту фичу имели в виду такой код: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Код: plaintext 1. 2. 3. 4. 5. 6. И это абсолютно корректный код. Модуль a.c не может модифицировать переменную max, а модуль b.c модифицирует, и a.c видит эти модификации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 19:48 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyИ это абсолютно корректный код. Вообще-то нет. Напоминаю, что речь о C90. Указанный код компилироваться не будет. Директива include в C указывается так: Код: plaintext 1. Комментарии в стандарте C89/C90 указываются так: Код: plaintext 1. а не в виде //. Даже если внести указанные мною попровки, то при компиляции получим ошибки (в принципе, ожидаемые): терминалbush@host-nix:~$ cd ~/test bush@host-nix:~/test$ gcc a.c b.c -o a.out -std=c90 /tmp/cccZd6Gp.o:(.data+0x0): multiple definition of `max' /tmp/ccoZXZt0.o:(.rodata+0x0): first defined here collect2: ошибка: выполнение ld завершилось с кодом возврата 1 Однако тема плавно куда-то ушла от заданного мною вопроса, как мне кажется. Я разобрался с вопросом темы. Проблема была в том, что изначально я указывал компилятору недостаточно опций и проверка на соответствие стандарту C90 проходила не столь педантично, как мне было нужно. Если выставить все нужные опции, то const действительно нельзя будет использовать (это ограничение закреплено в стандарте). На всякий случай покажу пример (нужные опции указал в комментарии, в начале кода - три варианта): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. Теперь я спокоен. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 20:42 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
CompositumДаже если внести указанные мною попровки, то при компиляции получим ошибки (в принципе, ожидаемые): терминалbush@host-nix:~$ cd ~/test bush@host-nix:~/test$ gcc a.c b.c -o a.out -std=c90 /tmp/cccZd6Gp.o:(.data+0x0): multiple definition of `max' /tmp/ccoZXZt0.o:(.rodata+0x0): first defined here collect2: ошибка: выполнение ld завершилось с кодом возврата 1 Данная ошибка говорит о том что вы кроме исправления моих опечаток (уж простите, в форумном редакторе нет компилятора для проверки, но поверьте я знаю как записывать команду #include), внесли существенное изменение - добавили инициализацию константы в ее определение. Иначе никак нельзя объяснить что в сегменте .rodata есть значение для этой константы. Если пофиксить эту самодеятельность, то мой код нормально компилируется и работает при сборке командой Код: plaintext Теперь я спокоен. :) Рано успокоились. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 22:54 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyИначе никак нельзя объяснить что в сегменте .rodata есть значение для этой константы. А отсутствие слова extern тут точно никаким боком не влияет?.. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 22:59 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovAnatoly MoskovskyИначе никак нельзя объяснить что в сегменте .rodata есть значение для этой константы. А отсутствие слова extern тут точно никаким боком не влияет?.. Может и влияет. Для начала нужно чтобы мы рассматривали один и тот же исходный код и версию компилятора и добились одинакового поведения. А потом уже можно будет говорить, какое поведение стандартно, а какое нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 23:28 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyДанная ошибка говорит о том что вы кроме исправления моих опечаток, внесли существенное изменение - добавили инициализацию константы в ее определение. Иначе никак нельзя объяснить что в сегменте .rodata есть значение для этой константы. Если пофиксить эту самодеятельность, то мой код нормально компилируется и работает при сборке командой Код: plaintext Теперь я спокоен. :) Рано успокоились. Проверил ещё раз. Да, вы правы, инициализацию добавлял. Убрал - заработало... Да, успокоился рано... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 23:47 |
|
||
|
Константы (const) не могут служить границами массивов в C?
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovAnatoly MoskovskyИначе никак нельзя объяснить что в сегменте .rodata есть значение для этой константы. А отсутствие слова extern тут точно никаким боком не влияет?.. Погуглил: в С, extern - по умолчанию для переменных без инициализации. Так что от его добавления ничего не должно измениться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.03.2013, 23:59 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38187002&tid=2020367]: |
0ms |
get settings: |
9ms |
get forum list: |
11ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
164ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
| others: | 290ms |
| total: | 546ms |

| 0 / 0 |
