LINUX.ORG.RU
Ответ на: комментарий от comp00

Чтобы быстрее понять указатели, не нужны никакие Шилдты, а тем более Страуструпы, которые еще больше запутают человека. Как вариант мне в свое время помогло осиливания того же x86 ассемблера, после чего сразу все стало понятно и больше вопросов не возникало.

grouzen ★★
()
Ответ на: комментарий от cdshines

Почитал K&R, кое-что из «Глава 5. Указатели и массивы». Понял мало, но по своей проблеме узнал, что для того, чтобы передавать двумерный массив в функцию без указания размерности нужно передавать указатель на указатель. Завтра буду курить.

puding ☆
() автор топика

Еще один платиновый тред. Одни неучи пытаются рассказать другим неучам то, чего сами не знают. dev во всём великолепии.

Чтобы быстрее понять указатели, не нужны никакие Шилдты, а тем более Страуструпы, которые еще больше запутают человека. Как вариант мне в свое время помогло осиливания того же x86 ассемблера, после чего сразу все стало понятно и больше вопросов не возникало.

Как же хорошо, что я знакомство с компьютером именно с ассемблера и начинал. (А если точнее, со схемотехники ЭВМ и принципов работы процессора.)

Все, кто пытается программировать, не зная, во что реально превращаются все объектно-ориентированные быдлокоды — поетнциальные обезьяны с гранатами. Никогда не знаешь, в какой момент вылезет их невежество и во что оно выльется.

anonymous
()
Ответ на: комментарий от tailgunner

Если ты говоришь о косвенности как о двойном (в общем случае - n-кратном) разыменовании указателя на указатель ([на указатель]*), то о какой косвенности может идти речь в случае

int arr[3][3] = {{1, 2, 3},
                 {4, 5, 6},
                 {7, 8, 9}};

, о котором говорю я?

Очевидно оно разворачивается в что-то типа

movl	$1, -48(%rbp)
movl	$2, -44(%rbp)
movl	$3, -40(%rbp)
movl	$4, -36(%rbp)
movl	$5, -32(%rbp)
movl	$6, -28(%rbp)
movl	$7, -24(%rbp)
movl	$8, -20(%rbp)
movl	$9, -16(%rbp)

т.о. доступ к элементу осуществляется именно по формуле из примера.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

в случае

int arr[3][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};

о котором говорю я?

А, ты уже об этом случае говоришь... а ведь совсем недавно было:

yoghurt> Разве доступ к элементу i,j в Т*[] не работает как *(base + i*rows + j)

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Между T[] и T[CONST] есть существенная разница.

Да, ещё раз посыпая голову пеплом говорю, что неправильно назвал тип, о котором шла речь изначально.

yoghurt ★★★★★
()
Ответ на: комментарий от comp00

Ну смысл в том, что многомерные массивы, хранятся не в виде абстрактного тела (таблица/куб etc) как удобно изображать человеку, а в виде указателей на указатели.

Двумерный массів: int[10][20] - честный сплошной участок памяті

То что вы описали - это массив одномерных массивов.

dzidzitop ★★
()
Ответ на: комментарий от cdshines

На этой неделе вообще по плюсам столько вопросов от тех, кто не читал k&r. Как будто k&r - многотомное собрание сочинений кернигана и риччи в 1200 страниц каждое, и всего 24 тома!!!

//фикседъ

nanoolinux ★★★★
()
Ответ на: комментарий от yoghurt

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

#include <stdlib.h>
#include <stdio.h>

typedef int MYCLASS;

#define WIDTH  3
#define HEIGHT 2 

MYCLASS a[WIDTH][HEIGHT];

typedef MYCLASS A[WIDTH][HEIGHT];


void print(A*a , int x,int y)
{

 for(int i=0;i<x;i++)
 for(int j=0;j<y;j++)
 { 
  printf("[%d][%d]=%d\n",i,j,(*a)[i][j]);
 }

}

int main(void)
{

 for(int i=0;i<WIDTH;i++)
 for(int j=0;j<HEIGHT;j++)
 { 
  a[i][j]=100*i+j;
 }

 A * a2=(A*)new int(WIDTH*HEIGHT);
 
 for(int i=0;i<WIDTH;i++)
 for(int j=0;j<HEIGHT;j++)
 { 
  (*a2)[i][j]=100*i+j;
 }
 print(&a,WIDTH,HEIGHT);
 printf("\n");
 print(a2,WIDTH,HEIGHT);
 return 0;
}

ilovewindows ★★★★★
()

Фух, разобрался.


//Задать размерность

int QwMatrixHeight = 20;
int QwMatrixWidth = 20;

//Создать матрицу

QwMatrixElement*** QwMatrix;


//Выделить память под элементы матрицы

for (int i = 0; i < QwMatrixHeight; i++) {

        for (int j = 0; j < QwMatrixWidth; j++) {

            QwMatrix[i][j] = new QwMatrixElement();

        }

    }


//Передача матрицы в функцию

void QwDoSomethingWithMatrix(QwMatrixElement*** matrix, int rows, int cols) {

    for (int i = 0; i < rows; i++) {

        for (int j = 0; j < cols; j++) {

            matrix[i][j]->someProperty = true;

        }

    }

}


//Использование в программе

QwDoSomethingWithMatrix(QwMatrix, QwMatrixHeight, QwMatrixWidth);

puding ☆
() автор топика
Ответ на: комментарий от tailgunner

Это, как правильно сказали выше, массив массивов, а не многомерный массив.

В его коде еще и выделение памяти под массивы отсутствует.

anonymous
()
Ответ на: комментарий от puding
template <typename T>
void QwDoSomethingWithMatrix(T *matrix, int rows, int cols) {

    for (int i = 0; i < rows-1; i++) {

        for (int j = 0; j < cols-1; j++) {

            matrix[i][j]->someProperty = true;

        }
    }
}
nanoolinux ★★★★
()
Последнее исправление: nanoolinux (всего исправлений: 1)
Ответ на: комментарий от puding
#include <array>
#include <cstdio>

template <typename T, size_t h, size_t w>
using Matrix = std::array<std::array<T, w>, h>;

struct Something {
    bool property;
    int value;
    Something() : property(true) {}
};

template <size_t h, size_t w>
void doSomething(Matrix<Something, h, w>& mx)
{
    int x = 0;
    for (auto& col : mx)
        for (auto& el : col) {
            printf("%p\n", &el);
            el.value = ++x;
        }
}

int main()
{
    printf("sizeof cell = %ld\n", sizeof(Something));

    constexpr size_t h = 3, w = 3;

    Matrix<Something, h, w> mx;
    // movb	$1, (%rsp)
    // movb	$1, 8(%rsp)
    // movb	$1, 16(%rsp)
    // movb	$1, 24(%rsp)
    // movb	$1, 32(%rsp)
    // movb	$1, 40(%rsp)
    // movb	$1, 48(%rsp)
    // movb	$1, 56(%rsp)
    // movb	$1, 64(%rsp)

    doSomething(mx);

    for (size_t i = 0; i < h; ++i) {
        printf("{ ");
        for (size_t j = 0; j < w; ++j)
            printf("(%p){%d %d} ", &mx[i][j], mx[i][j].property, mx[i][j].value);
        puts("}");
    }
}

/*

sizeof cell = 8
0x7ff0000d8
0x7ff0000e0
0x7ff0000e8
0x7ff0000f0
0x7ff0000f8
0x7ff000100
0x7ff000108
0x7ff000110
0x7ff000118
{ (0x7ff0000d8){1 1} (0x7ff0000e0){1 2} (0x7ff0000e8){1 3} }
{ (0x7ff0000f0){1 4} (0x7ff0000f8){1 5} (0x7ff000100){1 6} }
{ (0x7ff000108){1 7} (0x7ff000110){1 8} (0x7ff000118){1 9} }

 */

/*

  total heap usage: 0 allocs, 0 frees, 0 bytes allocated

 */

Обрати внимание на 0 аллокаций в куче, на код аллокации на стеке, на дефолтный конструктор, на два способа обхода и на непрерывный layout элементов матрицы в памяти.

Если h и w неизвестны на момент компиляции, то нужно делать как предложил tailgunner, то есть писать свой класс с аллокацией одним куском и доступом с помощью арифметики i * w + j индексов. На самом деле (по стандарту), для статических T[h][w] и std::array<std::array<T, w>, h> компилятор сам располагает их непрерывно в памяти и пишет ту же самую арифметику для индексов в ассемблер для [ i ][j].

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от trex6

std::vector< std::vector< T> >

std::vector<std::vector<int>> xs = {{1, 2, 3}, {1, 2}, {1}, {}};

for (auto const& col : xs) {
    for (auto const& el : col)
        printf("(%p)%d ", &el, el);
    puts("");
}

/*
(0x59f91d0)1 (0x59f91d4)2 (0x59f91d8)3 
(0x59f9220)1 (0x59f9224)2 
(0x59f9270)1 

*/

/*
  total heap usage: 7 allocs, 7 frees, 144 bytes allocated
 */

144/4 = 36, куда ему столько? :)

int xs[][3] = {{1, 2, 3}, {1, 2}, {1}, {}};

for (auto const& col : xs) {
    for (auto const& el : col)
        printf("(%p)%d ", &el, el);
    puts("");
}

/*
(0x7ff0000e0)1 (0x7ff0000e4)2 (0x7ff0000e8)3 
(0x7ff0000ec)1 (0x7ff0000f0)2 (0x7ff0000f4)0 
(0x7ff0000f8)1 (0x7ff0000fc)0 (0x7ff000100)0 
(0x7ff000104)0 (0x7ff000108)0 (0x7ff00010c)0 
 */

/*
  total heap usage: 0 allocs, 0 frees, 0 bytes allocated
 */

(0x7ff00010c + 4 - 0x7ff0000e0) / 4 = 12 = 4 * 3.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от anonymous

это может приводить к code bloating если юзаются много інстансов с разнымі размерностями

Если много разных h и w, то тоже — класс с size_t (const если нет resize -> realloc) h, w; T *data; и i * w + j в operator().

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от quasimoto

А если размерности нормальные взять? 500х500?

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

trex6 ★★★★★
()
Ответ на: комментарий от dzidzitop

многомерные массивы в памяти представляются именно как массивы одномерных массивов и никак иначе.

comp00 ★★★★
()
Ответ на: комментарий от puding

чего то вывыливается в SIGSEGV

Упрямый ты. Ну как хочешь : ССЗБ. Подсказываю последний раз: man new, delete

comp00 ★★★★
()
Последнее исправление: comp00 (всего исправлений: 1)
Ответ на: комментарий от comp00

рекомендую проверить. Сейчас под рукой GCC нет. Можно создать массив 2 на 2 и итерацией + печатью значений указателей на элементы проверіть.

anonymous
()
Ответ на: комментарий от anonymous
  1 #include<iostream>
  2 #define SIZE 4 
  3 int main(int argc, char **argv){
  4     int **array = new int*[SIZE];
  5     for(int i=0;i<SIZE;++i){
  6         array[i]=new int[SIZE];
  7     }
  8 
  9     for(int i=0; i<SIZE;++i){
 10         for(int j=0;j<SIZE;++j){
 11             std::cout<<" "<<&array[i][j];
 12         }
 13         std::cout<<"\n";
 14     }
 15     for(int i=0;i<SIZE;++i){
 16         delete array[i];
 17     }
 18     delete [] array;
 19     return 0;
 20 }

Результaт:

./tst 
 0x1989040 0x1989044 0x1989048 0x198904c
 0x1989060 0x1989064 0x1989068 0x198906c
 0x1989080 0x1989084 0x1989088 0x198908c
 0x19890a0 0x19890a4 0x19890a8 0x19890ac

Все правильно.

comp00 ★★★★
()
Последнее исправление: comp00 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Я поясню: понятно, что память под вектор выделяются последовательно. Но совершенно не факт, что вектор буде идти один за другим.

comp00 ★★★★
()
Ответ на: комментарий от anonymous

Многомерный массів: int array[2][2] = {{0, 1}, {2, 3}};

Это (у меня) многомерный массив. А ты путаешь кучу со стеком

comp00 ★★★★
()
Ответ на: комментарий от anonymous

тупняк.
Массивы могут выделяться на стеке или на куче
естественно, что это совершенно разные структуры, и способы организации памяти у них разные.
Тот факт что в википедии под array подразумевают выделение на стеке, не означает что массивы, выделенные на куче не являются массивами.
Да по факту это не многомерный массив, в массив указателей. Но знаешь ли, компьютер тоже не с 0 и 1 работает, как в школе преподают.

comp00 ★★★★
()
Последнее исправление: comp00 (всего исправлений: 1)
Ответ на: комментарий от anonymous

однако понимание что ключ-значение бд есть включающая в себя указатели общность облегчает понимание указателей и вообще различение/общее среди имя-именуемое

qulinxao ★★☆
()
Ответ на: комментарий от trex6

А если размерности нормальные взять?

А 3x3 или 4x4 это не нормальные?

500х500?

Чтобы стек сорвать это мало, наверно. Нужно побольше.

#include <cstdio>
#include <vector>

template <typename T>
class Matrix {

    T *data;

public:

    typedef T data_type;

    const size_t rows, cols;

    Matrix(const size_t rows, const size_t cols) :
        data(new T[rows * cols]), rows(rows), cols(cols) {}

    ~Matrix() { delete[] data; }

    T& operator()(const size_t i, const size_t j) const {
        return data[i * cols + j];
    }

};

int main()
{

#ifdef VECTOR

    std::vector<std::vector<int> > mx(ROWS);
    for (size_t i = 0; i < mx.size(); ++i) {
        mx[i].resize(COLS);
        for (size_t j = 0; j < mx[i].size(); ++j)
            mx[i][j] = i * j;
    }

    long long sum = 0;
    for (size_t i = 0; i < mx.size(); ++i)
        for (size_t j = 0; j < mx[i].size(); ++j)
            sum += mx[i][j];

    printf("%lld\n", sum);

#else

    Matrix<int> mx(ROWS, COLS);

    for (size_t i = 0; i < mx.rows; ++i)
        for (size_t j = 0; j < mx.cols; ++j)
            mx(i, j) = i * j;

    long long sum = 0;
    for (size_t i = 0; i < mx.rows; ++i)
        for (size_t j = 0; j < mx.cols; ++j)
            sum += mx(i, j);

    printf("%lld\n", sum);

#endif

}
$ ~ g++ -DVECTOR -DROWS=15000 -DCOLS=20000 -O1 mx.cc
$ ~ \time ./a.out
22497375075000000
1.01user 0.60system 0:01.69elapsed 95%CPU (0avgtext+0avgdata 4692848maxresident)k
0inputs+0outputs (0major+293433minor)pagefaults 0swaps
$ ~ g++ -DROWS=15000 -DCOLS=20000 -O1 mx.cc
$ ~ \time ./a.out
22497375075000000
0.59user 0.85system 0:01.48elapsed 97%CPU (0avgtext+0avgdata 4691488maxresident)k
128inputs+0outputs (1major+3035minor)pagefaults 0swaps
$ ~ g++ -DVECTOR -DROWS=15000 -DCOLS=20000 -O2 mx.cc
$ ~ \time ./a.out
22497375075000000
0.75user 0.56system 0:01.38elapsed 94%CPU (0avgtext+0avgdata 4692864maxresident)k
0inputs+0outputs (0major+293435minor)pagefaults 0swaps
$ ~ g++ -DROWS=15000 -DCOLS=20000 -O2 mx.cc
$ ~ \time ./a.out
22497375075000000
0.44user 0.33system 0:00.79elapsed 97%CPU (0avgtext+0avgdata 4690672maxresident)k
0inputs+0outputs (0major+1503minor)pagefaults 0swaps
$ ~ g++ -DVECTOR -DROWS=15000 -DCOLS=20000 -Ofast mx.cc
$ ~ \time ./a.out
22497375075000000
0.47user 0.60system 0:01.15elapsed 93%CPU (0avgtext+0avgdata 4692864maxresident)k
0inputs+0outputs (0major+293435minor)pagefaults 0swaps
$ ~ g++ -DROWS=15000 -DCOLS=20000 -Ofast mx.cc
$ ~ \time ./a.out
22497375075000000
0.40user 0.34system 0:00.76elapsed 98%CPU (0avgtext+0avgdata 4691456maxresident)k
0inputs+0outputs (0major+992minor)pagefaults 0swaps

в случае vector<vector (ROWS + 1) аллокаций и локальность хуже, у второго варианта одна аллокация и, соответственно, всё одним куском.

quasimoto ★★★★
()

тут на лоре уже было

#include <stdlib.h>
#include <stdio.h>
int g=0;
void* m_init(size_t t){
	int* a=(int*)malloc(t*sizeof(int));
	int i;
	for(i=0;i<t;i++){
	  a[i]=g++;
	}
	return a;
}
void * g_dynarr(char* sz){
	if(!sz[1]){
		 return m_init(sz[0]);//simple test

	}
	void**p=malloc(sz[0]*sizeof(void*));
	int i;for(i=0;i<sz[0];i++){
		p[i]=g_dynarr(sz+1);
	}
	return p;
}
void cl(void* a,char* sz){
	return ;
}
int main(int c,char **z){
	char sz[]={10,10,0,1,1,10,0};//if short need +2 but ++;

	int i,j,k,l,m,n;
	//int***** a=(int*****)g_dynarr(sz);//bad_idia for g_dynarr(NULL) and g_dynarr("")
	/* sz={1,2,3,4,5,10,0};
	   for(i=0;i<sz[0];i++){
		for(j=0;j<sz[1];j++){
			for(k=0;k<sz[2];k++){
				for(l=0;l<sz[3];k++){
					for(m=0;m<sz[4];m++){
						for(n=0;n<sz[5];n++){
							printf(" %d",a[i][j][k][l][m]);
						}
						printf("\n");
					}
				}
			}
		}
	}*/
	
	{//test 10x10
		int **a=(int**)g_dynarr(sz);
		for(i=0;i<sz[0];i++){
			for(j=0;j<sz[1];j++){
				printf(" %d",a[i][j]);
			}
			printf("\n");
		}
		cl(a,sz);
	}
	{//test 2x3x4;
		sz[0]=2;sz[1]=3;sz[2]=4;g=0;
		//sz[2]=10;
		sz[3]=0;
		int ***a=(int***)g_dynarr(sz);
		for(i=0;i<sz[0];i++){
			printf("plane %d\n",i);
			for(j=0;j<sz[1];j++){
				for(k=0;k<sz[2];k++){
					printf(" %d",a[i][j][k]);
				}
				printf("\n");
			}
		}
		cl(a,sz);
	}
	return 0;
	
}

на стек оверфлоу где то было - да и вообще отличная стратегия - берём большой кусок M - принимаем за ноль его начало и тогда развлекаемся номер есть смещение в этом массиве и конструкция M[M[....]]

qulinxao ★★☆
()

не благодари. 0[a+i][a+j]

#include <stdio.h>
#define N 3
#define M 5
#define sz (N+1)*(M+1)
int a[sz];
int main(){
	int i,j;
	for(i=0;i<sz;i++)a[i]=(i/(N+1))*1000+i%(N+1);

	for(i=0,j=0;i<=N;i++,j+=(M+1))a[i]=j;

	for(i=1;i<=N;i++){
		for(j=0;j<M+1;j++)
			printf("%d ",0[a+i][a+j]);
		printf("\n");
	}

	printf("sizeof int %d byte",sizeof(int));
	return 0;
}
qulinxao ★★☆
()

для лучшего понимания 0[M+row][M+column][M+z ;)]

#include <stdio.h>
#define N 2
#define M 7
#define sz (N+1)*(M)
int a[sz];
int main(){
	int i,j,t;
	for(i=0;i<sz;i++){
		t=(i/(M));
		a[i]=t*100+(i%(M));
	}
	for(i=0,j=0;i<=N;i++,j+=(M))a[i]=j;

	for(i=0;i<sz;printf("%d ",a[i++]));printf("\n");

	

	for(i=0;i<=N;i++){
		for(j=0;j<M;j++)
			printf("%d ",0[a+i][a+j]);
		printf("\n");
	}

	printf("sizeof int %d byte",sizeof(int));
	return 0;
}
qulinxao ★★☆
()

Почти дописал, вываливается в SIGSEGV в main при доступе к элементу матрицы, хотя в функции выполняется

#include <iostream>

using namespace std;

//Элемент матрицы

class someType {

private:

    bool state;

public:

    void setState(bool value) {

        if (value == true)
            state = true;
        else state = false;

    }

};

//Размерность матрицы, которую можно задавать

int rows;
int cols;

//Матрица

bool firstRun = true;
someType*** matrix;

//Передача матрицы в функцию

void doSomething(someType*** matrix, int currentRow, int currentCol) {

    matrix[currentRow][currentCol]->setState(true);

}

//Перестройка матрицы

void rebuildMatrix(someType*** matrix, int newRows, int newCols) {

    //Очистка

    if (firstRun == false) {

        for (int i = 0; i < rows; i++) {

            for (int j = 0; j < cols; j++) {

                delete matrix[i][j];

            }

        }

        firstRun = true;

    }

    rows = newRows;
    cols = newCols;

    //Выделение памяти

    matrix = new someType**[rows];

    for (int i = 0; i < rows; i++) {

        matrix[i] = new someType*[cols];

    }

    for (int i = 0; i < rows; i ++) {

        for (int j = 0; j < cols; j++) {

            matrix[i][j] = new someType;

        }

    }

    //Инициализация

    for (int i = 0; i < rows; i++) {

        for (int j = 0; j < cols; j++) {

            matrix[i][j]->setState(false);

        }
    }

}

int main() {

    //Создание матрицы

    rebuildMatrix(matrix, 10, 10);

    //Доступ к элементу матрицы

    matrix[9][9]->setState(true);

    //Вызов функции, в которую передается матрица

    doSomething(matrix, 9, 9);

    //Перестройка матрицы

    rebuildMatrix(matrix, 20, 20);

}
puding ☆
() автор топика

Т.е. здесь

    //Доступ к элементу матрицы

    matrix[9][9]->setState(true);

    //Вызов функции, в которую передается матрица

    doSomething(matrix, 9, 9);

вываливается.

puding ☆
() автор топика
Ответ на: комментарий от comp00

Массивы могут выделяться на стеке или на куче
естественно, что это совершенно разные структуры, и способы организации памяти у них разные.

Этот топик - просто праздник какой-то.

tailgunner ★★★★★
()
Ответ на: комментарий от puding

Тьфу,


void setState(bool value) {

        state = value;

    }

Сам поржал )

puding ☆
() автор топика
Ответ на: комментарий от puding

для лечения необходимо провести диагностику.

с какого языка пришёл?(у мя по некоторым кускам кода есть предположения)

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

В школе учили Паскаль, который мне не нравился тем, что не генерировал бинарников. Тогда я решил учить самый мощный язык, как мне показалось, который «может все». Вот, потихоньку быдлокодю. Хоть в математике я «полный NULL», писать все равно нравится.

puding ☆
() автор топика
Ответ на: комментарий от qulinxao

moar

В школе учили Паскаль, который я осилил по книжке за три дня. Сейчас уже забыл. Он мне не нравился тем, что не генерировал бинарников. Тогда я решил учить самый мощный язык, как мне показалось, который «может все». Вот, потихоньку быдлокодю. Хоть в математике я «полный NULL», писать все равно нравится.

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.