|
|
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
После трехлетнего перерыва пришлось вновь столкнуться с сями. Столько интересного! :) Возник вопрос: можно ли определить размерность (кол-строк и столбцов) двумерного массива? И еще один... А как передать в функцию произвольный двумерный массив? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.06.2005, 21:26 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
std::vector ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.06.2005, 22:24 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
не совсем понимаю... вектор - это класс векторов? но мне ведь нужен обычный массив... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.06.2005, 22:58 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
ФрилансерВозник вопрос: можно ли определить размерность (кол-строк и столбцов) двумерного массива? Нет. Двумерный массив в принципе ничем не отличается от одномерного. Когда ты задаешь i=arr[x,y] компилятор расшифровывает это в формулу i=*(arr+x*N+y) где N - длина строки. Обычно делают так: #define N 10 #define M 15 int arr[N, M]; for (i=0; i<N; i++) {} ФрилансерИ еще один... А как передать в функцию произвольный двумерный массив? Имя массива любой размерности это константный указатель на первую ячейку массива. Функция должна принимать указать определенного типа, а в вызове просто указываешь имя массива. Функция сама должна знать сколькомерный он. Но с точки зрения компилятора он всегда будет одномерным. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.06.2005, 23:37 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
Специально для любителей C++ и STL сделал пример. Я думаю, что он отвечает на все вопросы. Код: 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. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.06.2005, 23:43 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
White OwlКогда ты задаешь i=arr[x,y] компилятор разве не напишет C++Builder[C++ Error] Unit1.cpp(15): E2290 Array bounds missing ] ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.06.2005, 07:07 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
ФрилансерПосле трехлетнего перерыва пришлось вновь столкнуться с сями. Столько интересного! :) Возник вопрос: можно ли определить размерность (кол-строк и столбцов) двумерного массива? И еще один... А как передать в функцию произвольный двумерный массив? Лучше воспользуйся boost::array ;) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.06.2005, 10:34 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
White OwlИмя массива любой размерности это константный указатель на первую ячейку массива. Функция должна принимать указать определенного типа, а в вызове просто указываешь имя массива. Функция сама должна знать сколькомерный он. Но с точки зрения компилятора он всегда будет одномерным. Нет, массив и указатель это совершенно разные типы, которые не имеют ничего общего. Тем не менее, компилятор всегда заменяет тип аргумента функции с "массив" на "указатель на элемент", сохраняя тип элемента. Так что если бы мы написали Код: plaintext 1. 2. 3. Но автоконверсия с типа на тип не означает идентичности типов. int в double тоже автоконвертируется, и что? int - это double? Тем не менее массивы и указатели имеют разный linkage, так что мы не можем написать в *.h файле Код: plaintext 1. Код: plaintext 1. По поводу топика... В общем, на эту тему есть два подхода - Pure C и C++ C не проверяет границы массива, так что можно нахимичить такую вешь: struct IntegerArray { int elementCount; int arr[1]; }; Нам нужен массив со 100 элементами struct IntegerArray* ia = (struct IntegerArray*)_alloca(sizeof(struct IntegerArray) + sizeof(int) * 100 ) ia->elementCount = 100; Поскольку С не проверяет выхода за границы массива мы можем свободно юзать элементы с индексами 0 - 99, ибо свободная память есть. Для штампования таких структур можно написать макрос. В С++ более предпочтителен строгий контроль, и лучше использовать чего - то типа std::vector, оверхед будет небольшой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.06.2005, 16:56 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
Карабас Барабас White OwlКогда ты задаешь i=arr[x,y] компилятор разве не напишет C++Builder[C++ Error] Unit1.cpp(15): E2290 Array bounds missing ] ? Это смотря какой компилятор. Большинство умеет работать с двойным синтаксисом. То есть i=arr[x,y] полностью равняется i=arr[x][y]. Но некоторые действительно предпочитают более стандартный синтаксис i=arr[x][y]. А у некоторых (например у VC7) вообще каша - иногда они съедают arr[x,y] иногда ругаются. Пока я так и не понял в каком случае оно ругается а когда нет :) Сергей ИльичНет, массив и указатель это совершенно разные типы, которые не имеют ничего общего. Да??? :) Сергей Ильич Тем не менее массивы и указатели имеют разный linkage, так что мы не можем написать в *.h файле extern char foo[]; а в *.cpp char *foo = "a string"; Выскочит ошибка линковки, поскольку линкер не найдет символа foo, имеющего тип char[]. Естественно. Потому что в заголовке ты объявил КОНСТАНТНЫЙ указатель. А в коде, ты его пытаешься изменить. А вот например Код: plaintext 1. 2. 3. Сергей ИльичC не проверяет границы массива, так что можно нахимичить такую вешь: Намного чаще такие "безразмерные" массивы объявляют так: Код: plaintext 1. 2. 3. А твоя формула расчета на самом деле выделит память не под сто элементов, а под сто один :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.06.2005, 19:09 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
[quote White Owl] Естественно. Потому что в заголовке ты объявил КОНСТАНТНЫЙ указатель. А в коде, ты его пытаешься изменить. [/quote] Ни фига. extern означает, что где-то есть такой символ, но не в этом модуле. Компилятор пожимает плечами и делегирует работу линкеру. extern char foo[] означает что в в каком то модуле есть глобальный массив foo. char foo[] = "a string"; В данном случае отработает нормально, т.к. foo - массив char *foo = "a string"; не отработает, т.к. foo - указатель. http://www.prolegomena.net/Cstuff/ptrs/ptr.html [quote White Owl] > Между массивом и указателем нет ничего общего Да??? :) [/quote] А что общего между пачкой значений одинакового типа(массив) и значением, содержащин некий адрес (указатель)? [quote White Owl] Намного чаще такие "безразмерные" массивы объявляют так: struct IntegerArray { unsigned int elementCount; int arr[0]; }; Ноль - потому что считать реальный размер структуры потом будет проще. А твоя формула расчета на самом деле выделит память не под сто элементов, а под сто один :) [/quote] Микрософт в почему-то предпочитает вариант с одним элементом. Например, в структуре BITMAPINFO. Влом глядеть в стандарт, может быть в C89 массивы нулевого размера и запрещены. Лучше пускай четыре лишних байта лягут в стек, от греха подальше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.06.2005, 23:56 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
Ты эта... кнопочкой "предварительный просмотр" пользуйся, да. А то читать тебя очень затруднительно. Сергей ИльичНи фига. extern означает, что где-то есть такой символ, но не в этом модуле. Компилятор пожимает плечами и делегирует работу линкеру. Несовсем так. extern действительно означает что где-то, в каком-то из модулей есть переменная с таким-то именем, такого-то типа. И ее надо будет положить в сегмент DATA. Она может быть фактически объявленая в том же самом или другом модуле что и extern. В приниципе extern можно использовать для предопределения переменных. Сергей Ильичextern char foo[] char *foo = "a string"; не отработает, т.к. foo - указатель. Нет. Это не отработает, потому в первой строке утверждается что где то будет объявлен константный указатель. А фактически объявляется переменная. Ты читать умеешь? Третий раз уже пишу - имя массива это КОНСТАНТНЫЙ указатель. Не переменная указатель, а константа. Ты не можешь ее куда-то перенаправить. А в этом примере ты как раз и делаешь перенаправление. Сергей ИльичА что общего между пачкой значений одинакового типа(массив) и значением, содержащин некий адрес (указатель)? Значение ничего не может содержать. Это во первых. А во вторых.... ну как тебе объяснить.... разве что читать длинную лекцию про сегменты кода и памяти? :) В общем, пачка значений где-то находится, так? Значит у нас есть адрес первого элемента этой пачки (иначе мы до нее никогда не доберемся). Как этот адрес в нашей программе обозначен? Вот как раз через имя пачки значений :) Сергей ИльичЛучше пускай четыре лишних байта лягут в стек, от греха подальше. Какой стек, если ты память динамически выделяешь? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.06.2005, 00:54 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
White Owl Несовсем так. extern действительно означает что где-то, в каком-то из модулей есть переменная с таким-то именем, такого-то типа. И ее надо будет положить в сегмент DATA. Она может быть фактически объявленая в том же самом или другом модуле что и extern. В приниципе extern можно использовать для предопределения переменных. А почему в BSS не положить? Некоторые компиляторы кладут неинициализированный глобальный массив в .bss , некоторые - в .data . В результате иногда получается, что int foo[100][100] превратился в ~40k нулей в бинари. White Owl Сергей Ильичextern char foo[] char *foo = "a string"; не отработает, т.к. foo - указатель. Нет. Это не отработает, потому в первой строке утверждается что где то будет объявлен константный указатель. А фактически объявляется переменная. Ты читать умеешь? Третий раз уже пишу - имя массива это КОНСТАНТНЫЙ указатель. Не переменная указатель, а константа. Ты не можешь ее куда-то перенаправить. А в этом примере ты как раз и делаешь перенаправление. Какое перенаправление? Код: plaintext 1. 2. 3. Код: plaintext 1. 2. 3. Код: plaintext 1. 2. 3. White Owl Сергей ИльичА что общего между пачкой значений одинакового типа(массив) и значением, содержащин некий адрес (указатель)? ... В общем, пачка значений где-то находится, так? Значит у нас есть адрес первого элемента этой пачки (иначе мы до нее никогда не доберемся). Как этот адрес в нашей программе обозначен? Вот как раз через имя пачки значений :) А почему тогда структура - это не указатель? Ведь она тоже где-то лежит? White Owl Сергей ИльичЛучше пускай четыре лишних байта лягут в стек, от греха подальше. Какой стек, если ты память динамически выделяешь? :) _alloca() выделяет память в стеке. Очень многие реализации С предоставляют возможность выделять память в стеке. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.06.2005, 08:57 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
White OwlЭто смотря какой компилятор. Большинство умеет работать с двойным синтаксисом. То есть i=arr[x,y] полностью равняется i=arr[x][y]. Но некоторые действительно предпочитают более стандартный синтаксис i=arr[x][y]. Заявление о двойном синтаксисе является ... (как бы это помягче сказать). В C/C++ есть оператор "запятая". Результатом выполнения выражения x, y, z является z, поэтому: Код: plaintext 1. 2. Код: plaintext 1. 2. Удачи! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.06.2005, 18:25 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
White Owl Сергей ИльичНет, массив и указатель это совершенно разные типы, которые не имеют ничего общего. Да??? :) Да, массив приводится к указателю на свой первый элемент, но массив и указатель это две разные сущности. Массив самостоятельный элемент языка. авторТретий раз уже пишу - имя массива это КОНСТАНТНЫЙ указатель Не показывайте свое невежество - вы наговорили столько ерунды, что можно только развести руками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.06.2005, 18:34 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
Сергей ИльичА почему в BSS не положить? Некоторые компиляторы кладут неинициализированный глобальный массив в .bss , некоторые - в .data . Ну да, это зависит от компилятора. Может быть и там и там или даже на стеке. Сергей ИльичКакое перенаправление? Виноват, не "перенаправление", а "переопределение". Опечатался в пылу спора :) Сергей ИльичА почему тогда структура - это не указатель? Ведь она тоже где-то лежит? А имя структуры это тоже указатель :) Все точно так же как и с объявлеными в коде массивами. Код: plaintext 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2005, 17:59 |
|
||
|
как определить размерность массива в C++?
|
|||
|---|---|---|---|
|
#18+
ой как меня щас будут пинааать.... :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.06.2005, 18:36 |
|
||
|
|

start [/forum/topic.php?desktop=1&fid=57&tid=2033159]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
63ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
| others: | 213ms |
| total: | 366ms |

| 0 / 0 |
