Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > массивы переменой длины в кач. аргументов функции |
Автор: Pieris 24.4.2009, 20:46 | ||||||
Изучаю Си(до С++ пока дела нет), тема массивы переменной длины(стандарт С99), использую компилятор gcc, включенный в среду Dev-C++(WindowsXp). Это моя первая тема на форуме(надеюсь в правильном разделе) и я честно перелопатил форум в поисках подобных тем, но к сожалению ничего не нашел. Необходимо было написать программу с использованием функций, в качестве аргументов которых использовалась бы запись в стиле массивов переменной длины - одна для отображения двумерного массива, другая для копирования одного массива в другой. прототипы выглядят так:
определения так:
вызов функций вот так:
проблема заключена в том, что по отдельности, каждая из этих функций работает совершенно нормально( я проверял, закоментировав то одну то другую), но при попытке компиляции, когда они работают вместе, компилер выдает следующее: prior parameter's size depends on 'm' prior parameter's size depends on 'n' confused by earlier errors, bailing out Я честно пытался перевести эти мессаги, но всё что понял, так это то что компилер пытается сказать что-то типа: "размер предыдущего параметра зависит от ...", я не понимаю в чем дело, раздельно друг от друга функции работают, а если компилер хочет сказать что функции как-то связаны - то как такое может быть вообще? тем более что они используют разные переменные. Если у кого-нибудь есть соображения, пожалуйста поделитесь. |
Автор: Cheloveck 24.4.2009, 22:16 |
замени в аргументах функции double arr[x][y] на double *arr |
Автор: Pieris 24.4.2009, 22:31 | ||
Chelovek, дружище по-моему ты не врубаешься, я же сказал это стиль массивов переменной длины, характеризующийся тем, что сначала объявляются переменные, а затем они используются в качестве значений размера соответствующего массива, тем более если ты изучал Си, то должен знать что указание в качестве параметра простого указателя ничего не даст потомучто имя массива это адрес его первого элемента, кот. сам в свою очередь может быть массивом, например 5-ти элементов типа int, и указатель на int , такй как int *ptr работь не будет, но всё равно спасибо. |
Автор: Cheloveck 24.4.2009, 22:39 |
Врубаться, я врубаюсь. С одномерными массивами можно поступить так, как я сказал. Но с двухмерными, почему-то не работает, сейчас проверил, хз почему, пытаюсь разобраться. |
Автор: Pieris 24.4.2009, 22:52 | ||
объяви указатель вот так: (*ptr)[ n ], где n - размерность твоего массива, ну например если массив int array[3][5], то нужный указатель будет (*ptr)[5] - и всё будет работать (скобки в (*) обязательны), НО пардон, мы отклоняемся от темы. |
Автор: Rififi 24.4.2009, 22:54 |
Cheloveck, Но с двухмерными, почему-то не работает потому что вот это: массива это адрес его первого элемента неправда, и двумерный массив расположен в памяти не так как массив указателей. |
Автор: Cheloveck 24.4.2009, 22:55 |
http://http://www.linux.org.ru/view-message.jsp?msgid=658543 твоя проблема обсуждается. Почитай, может поможет. Практически то, что я и сказал)) |
Автор: Pieris 24.4.2009, 23:09 | ||
Во-первых я не понял, для меня ли твой мессидж, во-вторых ссылка не открывается, в-третьих варианты с традиционной записью параметров в стиле указателей или в стиле обычных массивов меня просто В ДАННОМ случае не интересуют, если ты представляешь что есть массив переменной длины и почему он так называется, то подобные ссылки и советы - просто бесполезный флуд. |
Автор: Cheloveck 24.4.2009, 23:15 | ||
Я отлично представляю, что есть массив переменной длины и как они лежат в памяти, если тебе не устраивают классические решения, то сорри. З.Ы. ссылка с другого форума, по ходу тут их лочат, но там предлагаются традиционные решения с указателями... |
Автор: Dov 24.4.2009, 23:21 |
Cheloveck, ты, скорее всего, путаешь массив переменной длины с динамическим массивом, отсюда и непонятки. |
Автор: Pieris 24.4.2009, 23:24 | ||
я не хотел быть резок, просто логично предположить что если функции по отдельности работают, значит их определения и вызовы совершенно корректны, и в даном случае неважно как массивы расположены в памяти, но компилятор ругается и не компилит, когда эти ф-ции исп-ся совместно, вот в чем вопрос. А по поводу традиционных решений - упражнение звучит так: "напишите функции с исп. в кач. аргументов запись в стиле массивов переменной длины", я могу написать их традиционно, но это просто не будет решением задачи. |
Автор: mes 24.4.2009, 23:31 |
напрасное обвинение, повнимательнее надо быть, там всего лишь пропущено двоеточие ![]() вот исправленная ссылка: http://www.linux.org.ru/view-message.jsp?msgid=658543 ![]() |
Автор: Pieris 24.4.2009, 23:42 | ||||
Определения функций я дал выше, компилер ругается не на вызовы функций а именно на определения, так что никаких общих дефайнов, и к тому же я пытался передавать параметры с исп. просто чисел наподобии:
но это ничего не меняет - прога не компилится... |
Автор: Anikmar 24.4.2009, 23:44 |
Приведите полный текст, если он не большой |
Автор: Pieris 24.4.2009, 23:57 | ||||
привожу полный код:
а ругается на др. фукцию:
|
Автор: Cheloveck 25.4.2009, 00:00 | ||||
У меня, допустим, не компилится даже одна (g++ 4.3.3-2)(gcc то же самое)... И ещё, компилятор от майкрософт вообще не потдерживает массивы с переменной длиной. |
Автор: Anikmar 25.4.2009, 00:08 | ||
Как я и предполагал - это чудо на BDS компилиться не хочет. Я бы делал так:
|
Автор: Dov 25.4.2009, 00:14 |
Anikmar, а нафига тогда первые 2 параметра у этих ф-ций? |
Автор: Pieris 25.4.2009, 00:26 | ||||||
да всё бы хорошо, только аргументы функций заданные в начале( int x, int y и тд) и есть переменные, описывающие размерность массива, и именно поэтому они объявляются раньше массива, стандарт С99 даже регламентирует форму записи без указния имен переменных в прототипах функций, использующих массивы переменной длины - вот так:
я это тоже пробовал, но в этом случае gcc честно признался, что он ещё не поддерживает это нововведение стандарта С99 |
Автор: Anikmar 25.4.2009, 00:38 |
А фиг его знает! ![]() Я просто так никогда не делал. ![]() |
Автор: Pieris 25.4.2009, 00:39 | ||
Chelovek, ты вот пишешь:
это и должно так быть потому что С99 это точка расхождения Си и С++, компилятор С++ и не будет это компилить, даже с одной такой функцией.Массивы переменной длины включены в стандарт си для облегчения исп. библиотек FORTRAN, кот. славится своими функциями для научных расчетов. Попробуй откомпилить задав компилятором по умолчанию Си, а не С++. |
Автор: J0ker 25.4.2009, 01:34 | ||
gcc-3.4 сломан: http://gcc.gnu.org/gcc-3.4/c99status.html http://gcc.gnu.org/ml/gcc-bugs/2004-04/msg02261.html Добавлено через 2 минуты и 20 секунд я вам вообще рекомендую забить на эту мертвую фичу - переходите на С++ и юзайте динамические массивы |
Автор: Pieris 25.4.2009, 11:07 |
J0ker, спасибо, я думаю это и есть ответ, а переходить на С++ мне рановато, там более я решил сначала в достаточной мере освоить чистый Си. Я уже было руки опустил, но тут неожиданно посоветовали включить опцию командной строки -std=c99, в среде Dev-C++ это делается(для тех кому придется сталкиваться) через Сервис-Параметры компилятора- и на первой вкладке поставить галочку напротив "Добавить следующие команды к запуску компилятора", после чего в поле пониже написать -std=c99 (и ессно ОК). Но есть одна особенность - при включенной опции Оптимизации, компилер даже при исп. опции -std=c99 не компилит, так что её придется отключить. Одним словом решение надено, я думаю тема закрыта! ![]() |
Автор: Anikmar 25.4.2009, 18:13 | ||
Золотые слова. Я даже сперва не врубился - что это за прикол. Ох... Чем изучать умирающие фичи - лучше сразу на плюсы. ИМХО: гораздо тяжелее переходить на плюсы хорошо освоив С, чем его зная чисто поверхностно. |
Автор: J0ker 25.4.2009, 22:46 | ||
С++ не является расширением С - никакой связи тут нет, можете смело переходить |
Автор: MAKCim 26.4.2009, 09:57 |
а лучше не быть таким категоричным плюсы не панацея и зачастую код только усложняется как в плане его понимания, так и в низкоуровневой реализации семантики |
Автор: J0ker 26.4.2009, 10:51 |
ну само-собой автомобиль-то завсегда сложнее велосипеда ![]() это смотря какую семантику реализовавать например если из автомобиля реализовывать семантику велосипеда, то да, усложняется тока нахрена оно надо? искусства ради? ну так мы уже наблюдали потуги реализации семантики автомобиля велосипедами - и смех и грех ![]() |
Автор: Anikmar 26.4.2009, 18:29 |
Ну я не на столько категоричен, чтобы плюсы назвать панацеей. Я так думаю только в сравнение конкретно Си и плюсов. Например сравнивать плюсы и делфи я не возьмусь ( в виду плохого знания делфи). А плюсы и С сравнивать могу - так как сам начинал с Си. И считаю, что нет вещей, которые с одинаковой трудоемкостью можно было бы сделать на СИ и нельзя на плюсах, а вот наоборот - спорно. Так что думаю все-таки плюсы более стоящая для изучения вещь. |
Автор: MAKCim 26.4.2009, 21:41 |
Anikmar, не вижу преимуществ С++ перед С ООП упоминать не стОит ![]() |
Автор: math64 26.4.2009, 22:10 | ||
Точка расхождения - создание C++. В C++ модификаторы const, extern, static имеют другое значение чем в C. const в C++ = static const в С Предварительное объявление переменной extern и затем static даёт в C++ extern, а в C static. |
Автор: mes 26.4.2009, 22:15 |
я с Си плохо знаком, вот что напрашивается : возможность перегрузки функций, типобезопасные шаблоны, средства разделения доступа (public, private в классе) виртуальные функции и т.д. ![]() |
Автор: Dov 26.4.2009, 22:19 |
счас выльется воды на 20 страниц и на этом всё закончится.. проходили уже.. ![]() |
Автор: MAKCim 26.4.2009, 22:19 |
mes, преимущества где? |
Автор: mes 26.4.2009, 22:29 |
тут тогда надо уточнить, что подразумевается под преимуществами, если приведенное выше не подпадает в эту категорию. и помойму пока не поздно перенести этот этот оффтоп в холивар. ![]() |
Автор: MAKCim 26.4.2009, 22:33 |
что делает его более эффективным во всех смыслах |
Автор: mes 26.4.2009, 22:38 |
эффективным с точки зрения работы результативного кода, или эффективность работы программиста сюда тоже относится ? |
Автор: MAKCim 26.4.2009, 22:41 |
mes, |
Автор: mes 27.4.2009, 01:41 |
учитывая то, что стандартный С++ позволяет практически все то, что и стандартный Си, но помимо этого имеет кучу дополнительных средств, начиная от перегрузки функции и заканчивая набором стандартных шаблонов, Вы считаете, что все эти дополнительные возможности не приносят никакой ощутимой эффективности ? |
Автор: Anikmar 27.4.2009, 09:17 | ||
Вот так рождаются баяны ![]() Это вопрос уже к религиозным войнам относится, хотя странно обсуждать и сравнивать Си и С++. Я понимаю С++ и С# или C++ и Делфи. Лично я, когда появился С++ считал, что Си мне хватит за глаза и незачем изучать какие-то дурацкие веяния типа ООП, классов, перегрузки и т.п. Но мнение свое изменил достаточно быстро. С точки зрения эффективности уже готового машинного кода - тут вся ответственность лежит на компиляторе. С точки зрения эффективности работы программиста - думаю спор просто глупый выйдет - естественно С++ по всем параметрам выиграет перед Си - так как С++ позволит сделать практически все то же, что и Си, а вот наоборот не получится. Так что думаю, что баян здесь развивать не стоит. |
Автор: MAKCim 27.4.2009, 10:01 | ||
еще как получится ![]() |
Автор: mes 27.4.2009, 11:43 |
но с ручными затратами. Взять хотя бы тот самый динамический полиморфизм - на cpp практически ничего не надо делать для его воплощения, плюс легко добавлять новые полиморфные типы в иерархию. А как с этим обстоит в Си ? |
Автор: math64 27.4.2009, 12:01 | ||
Единственное что в C сделать проще - инициализацию массивов и структур.
|
Автор: mes 27.4.2009, 12:34 |
к тому же насколько я знаю такое многоточие это расширение компилятора gcc, а не стандартный функционал. |
Автор: MAKCim 27.4.2009, 13:13 | ||
хорошо
|
Автор: MAKCim 27.4.2009, 13:29 |
я даже больше скажу sysfs и реализация kobject/kset в ядре linux - это сплошной полиморфизм на С там все предельно просто и эффективно я вообще-то специально оговорил, что не стОит начинать споры про ООП, т. к ООП != ЯП |
Автор: mes 27.4.2009, 14:16 | ||
MAKCim, приведенный код, работает также и на плюсах, однако там так не пишут. почему если помимо этого способа, есть еще другой, то выбор остановился за вторым ? И вот еще, а то никак не пойму, Вы считаете, что 1. тех средств что в Си достаточно, и можно выкрутиться в любой ситуации 2. тех средств что в Си явно достаточно, и предлагаемые возможности С++ просто излишни.
так вроде пока не затрагивали: в частности полиморфизм свойствен далеко не только ООП. Ну а вобще я думаю подобный спор можно решить, только сравнив изящность двух решений одной небольшой, но показательной задачи.. Осталось только подобрать такую задачку ![]() |
Автор: MAKCim 27.4.2009, 18:10 | ||||||||
да
да
ну как бы "полиморфизм-наследование-инкапсуляция" ![]()
для меня все очевидно я этих задач уже достаточно много решил мою позицию никому не навязываю, но и доказывать никому ничего не буду |
Автор: Pieris 27.4.2009, 23:50 |
Раньше я конечно просматривал программерские форумы, но пока не поучавствовал сам, не почувствовал, насколько у людей прослеживается тенденция отступать собственно от темы. Вряд-ли это есть хорошо, хотя бы потому, что сторонний человек, придя на интересующую его ветку форума, может просто не увидеть за деревьями леса (читай решения конкретного вопроса за обсуждениями сторонних тем). Не желая поддерживать эту тенденцию, я хочу вкрадце резюмировать информацию по существу вопроса:
|
Автор: mes 28.4.2009, 09:37 |
насколько я понимаю, для обработки статических массивов любой размерности. |
Автор: math64 28.4.2009, 10:40 |
Массив выделяется на стеке, он не статический, но нужно чтобы размер стека был достаточен для размещения такого массива. Добавлено через 3 минуты и 2 секунды это про массив исопльзуемый в функции. массив передаваемый через параметры может быть выделен где угодно - хоть статический, хоть на стеке, хоть с помощью malloc(). |
Автор: mes 28.4.2009, 12:01 | ||||
Статический массив - противопоставление динамическому массиву и о том где выделено для него память не говорится. Выражение
Я растолковал, что можно будет в функцию принимающую массив переменной длины, передать любой многомерный массив. Разница между многомерным статическим и динамическим массивом в Си, то что первый линеен, а второй представлен как многоуровневый массив указателей. (т.е **...) Соответсвенно передать двухмерный динамический массив как массив переменной длины не возможно. Но можно передать одну из его размерностей и рассматривать ее как двухмерный массив. Хотя вполне допускаю, что не совсем точно понял мысль. ![]() |
Автор: Dov 28.4.2009, 12:15 | ||
mes, массив переменной длины подразумевает то, что его размеры компилятор вычисляет не на этапе компиляции (как у обычных статических массивов, где размеры задаются константами), а во время работы программы. В этом плане, по моему мнению, речь о динамических массивах не идёт, по вышеизложенной причине. ![]() Добавлено @ 12:19 т.е. можно сделать так:
здесь при каждом вызове ф-ции размеры массива могут меняться. |
Автор: azesmcar 28.4.2009, 14:14 | ||||||||
![]() Добавлено @ 14:16 ![]() Это шедевр ![]() тема началась с
развернулась дискуссия на 4 страницы..и на последней странице я вижу сообщение
![]() Добавлено через 7 минут и 3 секунды Dov
может вот так имелось ввиду? |
Автор: math64 28.4.2009, 14:41 | ||||
Имелось ввиду не это
Здесь при каждом вызове (с разными аргументами) генерируется свой код. И кроме тог cols, rows должны быть константами.
|
Автор: MAKCim 28.4.2009, 14:42 |
azesmcar, будет |
Автор: azesmcar 28.4.2009, 14:51 | ||
![]() Выдаст что-то вроде expected constant expression. Добавлено через 11 минут и 47 секунд ![]() даже если этот код где-то и работает - этот код непереносим. |
Автор: mes 28.4.2009, 15:15 | ||
не из того стандарта выдержка ![]()
![]() |
Автор: azesmcar 28.4.2009, 15:17 |
mes аааа ![]() ну извиняйте..не прочитал все 4 страницы..я думал речь о С++ идет ![]() Развели дискуссию сам черт ногу сломает ![]() |
Автор: math64 28.4.2009, 15:49 |
Как ни странно, работает, даже если файл дать расширение .cpp (компилятор gcc, естественно) |
Автор: azesmcar 28.4.2009, 15:54 | ||||||
Ему наплевать на расширение.
этого хватит. а вот на визуал студии - не работает. 1>c:\my projects\dd\dd\main.c(5) : error C2057: expected constant expression 1>c:\my projects\dd\dd\main.c(5) : error C2466: cannot allocate an array of constant size 0 1>c:\my projects\dd\dd\main.c(5) : error C2057: expected constant expression 1>c:\my projects\dd\dd\main.c(5) : error C2466: cannot allocate an array of constant size 0 1>c:\my projects\dd\dd\main.c(5) : error C2087: 'arr' : missing subscript 1>c:\my projects\dd\dd\main.c(5) : error C2133: 'arr' : unknown size Добавлено через 14 минут и 19 секунд Поскольку привел издержку из стандарта (привел из неправильного ![]()
Но студия все равно не компилирует ![]() |
Автор: UnrealMan 28.4.2009, 18:54 | ||||
По этому поводу уже был один эпический holywar: http://forum.vingrad.ru/forum/topic-230321/kw-%D1%81++/view-all.html
Наверное, было бы правильнее сказать так: массивы переменной длины входят в текущий стандарт в C, но не входят в текущий стандарт C++. Некоторые гнутые компиляторы C++ поддерживают массивы переменной длины в качестве расширения. |