Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / как определить размерность массива в C++? / 17 сообщений из 17, страница 1 из 1
09.06.2005, 21:26
    #33110601
Фрилансер
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
После трехлетнего перерыва пришлось вновь столкнуться с сями. Столько интересного! :)
Возник вопрос: можно ли определить размерность (кол-строк и столбцов) двумерного массива?
И еще один... А как передать в функцию произвольный двумерный массив?
...
Рейтинг: 0 / 0
09.06.2005, 22:24
    #33110647
Guest12
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
std::vector ?
...
Рейтинг: 0 / 0
09.06.2005, 22:58
    #33110664
Фрилансер
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
не совсем понимаю...
вектор - это класс векторов? но мне ведь нужен обычный массив...
...
Рейтинг: 0 / 0
09.06.2005, 23:37
    #33110688
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
ФрилансерВозник вопрос: можно ли определить размерность (кол-строк и столбцов) двумерного массива?
Нет. Двумерный массив в принципе ничем не отличается от одномерного. Когда ты задаешь 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.
int foo(int *arr, int RowToCount, int SizeOfRow) {
  int sum, i;
  sum =  0 ;
  for(i = RowToCount*SizeOfRow; i < (RowToCount+ 1 )*SizeOfRow; i++) {
    sum += arr[i];
  }
  return sum;
}

int a1[ 3 , 3 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
printf("sum of second row is: %d\n", foo(a1,  1 ,  3 ));
...
Рейтинг: 0 / 0
09.06.2005, 23:43
    #33110692
Землекоп
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
Специально для любителей 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.
#include <vector>
#include <iostream>

template <typename T>
class array2
{
public:
  array2(){};
  array2(int r, int c)
  {
	rows=r;
	cols=c;
    for(int i= 0 ; i<rows; ++i)
    {
      data.push_back(std::vector<T>(cols));
    }
  }
  

  inline std::vector<T> & operator[](int i) { return data[i]; }

  inline const std::vector<T> & operator[] (int i) const { return data[i]; }
  int rows, cols;
private:
  std::vector<std::vector<T> > data;  
};
  
void myprint(array2<int> &a)
	{
	for(int i= 0 ; i<a.rows; ++i)
		{
		for(int j= 0 ; j<a.cols; ++j)
			{
			std::cout << a[i][j] <<"  ";
			}
		std::cout << std::endl;
		}
	}
int main()
 {
 array2<int>a( 10 , 3 );
 for(int i= 0 ; i< 10 ; ++i)
   for(int j= 0 ; j< 3 ; ++j)
     {
     a[i][j] = i+j;
     }

 myprint(a);
 return  0 ;
 }


...
Рейтинг: 0 / 0
10.06.2005, 07:07
    #33110811
Карабас Барабас
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
White OwlКогда ты задаешь i=arr[x,y] компилятор разве не напишет C++Builder[C++ Error] Unit1.cpp(15): E2290 Array bounds missing ] ?
...
Рейтинг: 0 / 0
10.06.2005, 10:34
    #33111145
Интегратор
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
ФрилансерПосле трехлетнего перерыва пришлось вновь столкнуться с сями. Столько интересного! :)
Возник вопрос: можно ли определить размерность (кол-строк и столбцов) двумерного массива?
И еще один... А как передать в функцию произвольный двумерный массив?

Лучше воспользуйся boost::array ;)
...
Рейтинг: 0 / 0
10.06.2005, 16:56
    #33112452
Сергей Ильич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
White OwlИмя массива любой размерности это константный указатель на первую ячейку массива. Функция должна принимать указать определенного типа, а в вызове просто указываешь имя массива. Функция сама должна знать сколькомерный он. Но с точки зрения компилятора он всегда будет одномерным.

Нет, массив и указатель это совершенно разные типы, которые не имеют ничего общего.
Тем не менее, компилятор всегда заменяет тип аргумента функции с "массив" на "указатель на элемент", сохраняя тип элемента. Так что если бы мы написали
Код: plaintext
1.
2.
3.
void foo(int arg[ 10 ][ 10 ]){
...
}
Компилятор заменит тип arg c int[10][10] на тип *int[10].

Но автоконверсия с типа на тип не означает идентичности типов. int в double тоже автоконвертируется, и что? int - это double?

Тем не менее массивы и указатели имеют разный linkage, так что мы не можем написать в *.h файле
Код: plaintext
1.
extern char foo[];
а в *.cpp
Код: plaintext
1.
char *foo = "a string";
Выскочит ошибка линковки, поскольку линкер не найдет символа foo, имеющего тип char[].

По поводу топика...
В общем, на эту тему есть два подхода - 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, оверхед будет небольшой.
...
Рейтинг: 0 / 0
10.06.2005, 19:09
    #33112753
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
Карабас Барабас 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.
extern char foo[];
char foo[ 10 ]="abcdefghij";
char *foo1;
foo1 = foo;
отработает без проблем, а если посмотришь на ассемблерный код - обнаружишь простое присвоение :)

Сергей ИльичC не проверяет границы массива, так что можно нахимичить такую вешь:
Намного чаще такие "безразмерные" массивы объявляют так:
Код: plaintext
1.
2.
3.
struct IntegerArray {
  unsigned int elementCount;
  int arr[ 0 ];
};
Ноль - потому что считать реальный размер структуры потом будет проще.
А твоя формула расчета на самом деле выделит память не под сто элементов, а под сто один :)
...
Рейтинг: 0 / 0
10.06.2005, 23:56
    #33112952
Сергей Ильич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
[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 массивы нулевого размера и запрещены.

Лучше пускай четыре лишних байта лягут в стек, от греха подальше.
...
Рейтинг: 0 / 0
11.06.2005, 00:54
    #33112977
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
Ты эта... кнопочкой "предварительный просмотр" пользуйся, да. А то читать тебя очень затруднительно.

Сергей ИльичНи фига. extern означает, что где-то есть такой символ, но не в этом модуле. Компилятор пожимает плечами и делегирует работу линкеру.
Несовсем так. extern действительно означает что где-то, в каком-то из модулей есть переменная с таким-то именем, такого-то типа. И ее надо будет положить в сегмент DATA. Она может быть фактически объявленая в том же самом или другом модуле что и extern. В приниципе extern можно использовать для предопределения переменных.

Сергей Ильичextern char foo[]
char *foo = "a string";
не отработает, т.к. foo - указатель.
Нет. Это не отработает, потому в первой строке утверждается что где то будет объявлен константный указатель. А фактически объявляется переменная. Ты читать умеешь? Третий раз уже пишу - имя массива это КОНСТАНТНЫЙ указатель. Не переменная указатель, а константа. Ты не можешь ее куда-то перенаправить. А в этом примере ты как раз и делаешь перенаправление.

Сергей ИльичА что общего между пачкой значений одинакового типа(массив) и значением, содержащин некий адрес (указатель)?
Значение ничего не может содержать. Это во первых.
А во вторых.... ну как тебе объяснить.... разве что читать длинную лекцию про сегменты кода и памяти? :) В общем, пачка значений где-то находится, так? Значит у нас есть адрес первого элемента этой пачки (иначе мы до нее никогда не доберемся). Как этот адрес в нашей программе обозначен? Вот как раз через имя пачки значений :)

Сергей ИльичЛучше пускай четыре лишних байта лягут в стек, от греха подальше.
Какой стек, если ты память динамически выделяешь? :)
...
Рейтинг: 0 / 0
12.06.2005, 08:57
    #33113479
Сергей Ильич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
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.
extern char foo[];

char foo[] = "a string";
Это работает

Код: plaintext
1.
2.
3.
extern char *const foo;

char *const foo = "a string";
Это тоже работает. Заметь - указатель константный.

Код: plaintext
1.
2.
3.
extern char foo[];

char *const foo = "a string";
Это не работает.

White Owl
Сергей ИльичА что общего между пачкой значений одинакового типа(массив) и значением, содержащин некий адрес (указатель)?
...
В общем, пачка значений где-то находится, так? Значит у нас есть адрес первого элемента этой пачки (иначе мы до нее никогда не доберемся). Как этот адрес в нашей программе обозначен? Вот как раз через имя пачки значений :)

А почему тогда структура - это не указатель? Ведь она тоже где-то лежит?

White Owl
Сергей ИльичЛучше пускай четыре лишних байта лягут в стек, от греха подальше.
Какой стек, если ты память динамически выделяешь? :)
_alloca() выделяет память в стеке. Очень многие реализации С предоставляют возможность выделять память в стеке.
...
Рейтинг: 0 / 0
12.06.2005, 18:25
    #33113712
Анатолий Широков
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
White OwlЭто смотря какой компилятор. Большинство умеет работать с двойным синтаксисом. То есть i=arr[x,y] полностью равняется i=arr[x][y]. Но некоторые действительно предпочитают более стандартный синтаксис i=arr[x][y].


Заявление о двойном синтаксисе является ... (как бы это помягче сказать). В C/C++ есть оператор "запятая". Результатом выполнения выражения x, y, z является z, поэтому:

Код: plaintext
1.
2.
int arr[ 10 ,  15 ];
arr[ 0 ,  1 ] =  100 ;
для любого компилятора тождественно
Код: plaintext
1.
2.
int arr[ 15 ];
arr[ 1 ] =  100 ;

Удачи!
...
Рейтинг: 0 / 0
12.06.2005, 18:34
    #33113715
Анатолий Широков
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
White Owl Сергей ИльичНет, массив и указатель это совершенно разные типы, которые не имеют ничего общего.
Да??? :)


Да, массив приводится к указателю на свой первый элемент, но массив и указатель это две разные сущности. Массив самостоятельный элемент языка.

авторТретий раз уже пишу - имя массива это КОНСТАНТНЫЙ указатель

Не показывайте свое невежество - вы наговорили столько ерунды, что можно только развести руками.
...
Рейтинг: 0 / 0
13.06.2005, 17:59
    #33114464
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
Сергей ИльичА почему в BSS не положить? Некоторые компиляторы кладут неинициализированный глобальный массив в .bss , некоторые - в .data .
Ну да, это зависит от компилятора. Может быть и там и там или даже на стеке.

Сергей ИльичКакое перенаправление?
Виноват, не "перенаправление", а "переопределение". Опечатался в пылу спора :)

Сергей ИльичА почему тогда структура - это не указатель? Ведь она тоже где-то лежит?
А имя структуры это тоже указатель :) Все точно так же как и с объявлеными в коде массивами.
Код: plaintext
1.
2.
3.
4.
5.
typedef struct {
  int x,y;
} POINT;

POINT p, *pp;
pp = p;
Работает без малейших проблем. А вот p=pp уже даст ошибку компилятора. Все точно так же как и с массивами.
...
Рейтинг: 0 / 0
13.06.2005, 18:36
    #33114524
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
ой как меня щас будут пинааать.... :)
...
Рейтинг: 0 / 0
13.06.2005, 20:16
    #33114620
Сергей Ильич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как определить размерность массива в C++?
White Owlой как меня щас будут пинааать.... :)
К сожалению, тема разошлась с той, ради чего я начинал этот спор.
А ради чего я начинал, я забыл. Так что расслабься.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / как определить размерность массива в C++? / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]