На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Определение параметров массивов в языке С
    1. В книге Харбисона и Стила "Язык С с примерами" (2011 года, стр. 162) указывается, что запись функции вида:
    void getArray(int nstr, int ncol, int a[nstr][ncol]) {...}
    является корректным. Я не очень понял, как тогда нужно объявлять массив "a" в основной программе для правильного вызова функции.
    2. В книге по C, по-моему, Шилда указано, что в функциях можно использовать локальные массивы конструкции:
    ExpandedWrap disabled
      void getArray(int nstr, int ncol)
      {
      int a[nstr][ncol];
      }

    Ошибки
    ExpandedWrap disabled
      error C2057: требуется константное выражение
      error C2466: невозможно выделить память для массива постоянного нулевого размера
      error C2057: требуется константное выражение
      error C2466: невозможно выделить память для массива постоянного нулевого размера
      error C2087: a: отсутствует индекс
    Может быть я неправильно понял изложенное в этих книгах? Прикрепляю проект, который компилировал и как С++, и как С. Посмотрите, пожалуйста, может быть я что-то делаю неправильно.
    Прикреплённый файлПрикреплённый файлMy_ConsConly.zip (2.21 Кбайт, скачиваний: 135)
    Сообщение отредактировано: tumanovalex -
      Цитата tumanovalex @
      2. В книге по C, по-моему, Шилда указано, что в функциях можно использовать локальные массивы конструкции:
      Или ты не так понял, или выкинь книгу. При объявлении массива nrow и ncol должны быть константами.
        В Стандарте C99 разрешаются локальные в функциях массивы с неконстанстными размерами. В Стандарте C++ такого нет за ненадобностью. Но по-любому массивы в параметрах функций сводятся к указателям. Оно является коррекным в любой ревизии C/C++, но будет игнорироваться.
          Цитата Adil @
          Цитата tumanovalex @
          2. В книге по C, по-моему, Шилда указано, что в функциях можно использовать локальные массивы конструкции:
          Или ты не так понял, или выкинь книгу. При объявлении массива nrow и ncol должны быть константами.

          В С++. В С - можно и не константами(в C99).
          Кстати, новый же стандарт C++ хотели привести в соответствие с C99 :-?
            Цитата D_KEY @
            Кстати, новый же стандарт C++ хотели привести в соответствие с C99
            C99 так и не стал основным стандартом C. Все еще существуют компиляторы не поддерживаюшие этот стандарт, и это считается нормальным.

            Учитывая, что в C++ и массивы C89 с константным размером считаются плохим тоном, то становится понятным, почему в стандарт C++ не стали вводить массивы с неизвестным на момент компиляции размером. Тем более, что у C99 и C++ и так хватает несоответствий. Вдобавок подобная таким массивам конструкция, реализованная средствами C++, практически не отличается результатом компиляции.
              Цитата amk @
              C99 так и не стал основным стандартом C

              А уже вышел C11...
                Цитата amk @
                Вдобавок подобная таким массивам конструкция, реализованная средствами C++, практически не отличается результатом компиляции.

                Это какая же? Разве что извращаться через placement new.
                  Зачем? std::vector<> на что?
                    Цитата Qraizer @
                    Зачем? std::vector<> на что?

                    std::vector<> работает с динамической памятью. Можно, конечно, заставить его работать со стэком, но это уже извращение. ИМХО.
                    Сообщение отредактировано: D_KEY -
                      Ну и что? Контракты те же.
                        Цитата Qraizer @
                        Ну и что? Контракты те же.

                        "Контракты" даже лучше у вектора :) Тут же работа со стэком и ключевая особенность variable-length массивов именно в этом.
                        Разговор изначально вообще-то о С был.
                        Но я так и не понял, почему в новом стандарте С++ все-таки отказались от обещанной совместимости с C99?
                          Цитата tumanovalex @
                          1. В книге Харбисона и Стила "Язык С с примерами" (2011 года, стр. 162) указывается, что запись функции вида:
                          void getArray(int nstr, int ncol, int a[nstr][ncol]) {...}
                          является корректным. Я не очень понял, как тогда нужно объявлять массив "a" в основной программе для правильного вызова функции.
                          2. В книге по C, по-моему, Шилда указано, что в функциях можно использовать локальные массивы конструкции:
                          ExpandedWrap disabled
                            void getArray(int nstr, int ncol)
                            {
                            int a[nstr][ncol];
                            }

                          Ошибки
                          Может быть я неправильно понял изложенное в этих книгах? Прикрепляю проект, который компилировал и как С++, и как С.

                          1. В книге Харбисона и Стила "Язык С с примерами" (2011 года, стр. 162) указывается, что запись функции вида:
                          void getArray(int nstr, int ncol, int a[nstr][ncol]) {...}
                          является корректным. Я не очень понял, как тогда нужно объявлять массив "a" в основной программе для правильного вызова функции.
                          2. В книге по C, по-моему, Шилда указано, что в функциях можно использовать локальные массивы конструкции:
                          ExpandedWrap disabled
                            void getArray(int nstr, int ncol)
                            {
                            int a[nstr][ncol];
                            }

                          Ошибки
                          Может быть я неправильно понял изложенное в этих книгах? Прикрепляю проект, который компилировал и как С++, и как С.

                          Первый ваш вопрос. Для вызова функции getArray нужно в первых двух параметрах указать размеррности массива, передаваемого в качестве третьего аргумента.

                          Например,

                          ExpandedWrap disabled
                            int main( void )
                            {
                               int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
                             
                               getArray( 2, 3, a );
                            }


                          Второй ваш вопрос. ваш компилятор выдает сообщения об ошибке, так как он, скорей всего, просто не поддерживает стандарт языка С99.
                          Если вы программируете на С, то вам очевидно нужно использовать компилятор, который поддерживает стандарт С99.
                            Цитата D_KEY @
                            Тут же работа со стэком и ключевая особенность variable-length массивов именно в этом.
                            Да ну? А я всегда считал, что это не цель, а средство её достижения. А целью является "локальность" выделяемой памяти. Когда-то этим занималась _alloca(), и такие массивы являются результатом её стандартизации.
                              Цитата Qraizer @
                              Цитата D_KEY @
                              Тут же работа со стэком и ключевая особенность variable-length массивов именно в этом.
                              Да ну? А я всегда считал, что это не цель, а средство её достижения. А целью является "локальность" выделяемой памяти.

                              Я одного не понял, с чем ты спорил? Стэк == локальная память.
                              Сообщение отредактировано: D_KEY -
                                С тем, что std::vector<> якобы не является заменой. Является. Поэтому эта C99-фича в Плюсах не нужна.
                                  Цитата Qraizer @
                                  С тем, что std::vector<> якобы не является заменой. Является. Поэтому эта C99-фича в Плюсах не нужна.

                                  Она нужна в плюсах исключительно для совместимости с C99.

                                  Добавлено
                                  Цитата Qraizer @
                                  С тем, что std::vector<> якобы не является заменой. Является.

                                  Не совсем. Одно из свойств "локальной" памяти - более быстрая работа и локальный контекст распределения(т.е. нас не волнуют вопросы распределения и освобождения, проблемы многопоточной среды и т.п.). Вектор же не работает с автоматической памятью, он просто автоматически освобождает динамическую.
                                  Сообщение отредактировано: D_KEY -
                                    Цитата
                                    Вектор же не работает с автоматической памятью, он просто автоматически освобождает динамическую.

                                    А мы vector<int, pool_allocator_or_whatever<int>> возмём, и он тоже будет работать с локальной памятью. Не на стеке, конечно, но от этого суть дела не меняется.

                                    Добавлено
                                    Цитата catr @
                                    А мы vector<int, pool_allocator_or_whatever<int>> возмём, и он тоже будет работать с локальной памятью. Не на стеке, конечно, но от этого суть дела не меняется.

                                    Причём это будет даже лучше размещения массива на стеке, так как переполнение стека черевато крахом программы, а нехватка памяти в пуле может привести всего-лишь к исключению.
                                      Цитата catr @
                                      Цитата
                                      Вектор же не работает с автоматической памятью, он просто автоматически освобождает динамическую.

                                      А мы vector<int, pool_allocator_or_whatever<int>> возмём, и он тоже будет работать с локальной памятью. Не на стеке, конечно, но от этого суть дела не меняется.

                                      Добавлено
                                      Цитата catr @
                                      А мы vector<int, pool_allocator_or_whatever<int>> возмём, и он тоже будет работать с локальной памятью. Не на стеке, конечно, но от этого суть дела не меняется.

                                      Причём это будет даже лучше размещения массива на стеке, так как переполнение стека черевато крахом программы, а нехватка памяти в пуле может привести всего-лишь к исключению.

                                      Так с этим-то никто не спорит.
                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                      0 пользователей:


                                      Рейтинг@Mail.ru
                                      [ Script execution time: 0.1019 ]   [ 18 queries used ]   [ Generated: 1.07.26, 10:30 GMT ]