Преобразование указателей
От: Punk Россия  
Дата: 14.12.01 16:43
Оценка:
#include "stdafx.h"

void conv(int s, int ** a)
{
int i, j;
for (i = 0; i < s; i++)
for (j = 0; j < s; j++)
printf("%lf\n", a[i][j] );
}


int main(int argc, char* argv[])
{
int a[2][2];
a[0][0] = 7;
a[0][1] = 4;
a[1][0] = 2;
a[1][1] = 9;
conv(2, (int**)(a));
return 0;
}

Этот код не работает
Re: Преобразование указателей
От: Андрей Тарасевич Беларусь  
Дата: 14.12.01 17:07
Оценка:
Здравствуйте Punk, Вы писали:

P>#include "stdafx.h"


P>void conv(int s, int ** a)

P>{
P> int i, j;
P> for (i = 0; i < s; i++)
P> for (j = 0; j < s; j++)
P> printf("%lf\n", a[i][j] );
P>}


P>int main(int argc, char* argv[])

P>{
P> int a[2][2];
P> a[0][0] = 7;
P> a[0][1] = 4;
P> a[1][0] = 2;
P> a[1][1] = 9;
P> conv(2, (int**)(a));
P> return 0;
P>}

P>Этот код не работает


И не должен. Передать массив, декларированный как 'T a[N][M]' в функцию так, чтобы внутри функции его размер не был известен на стадии компиляции, невозможно. Придется организовать эот массив по другому. Посмотри соседние сообщения. Например,
http://www.rsdn.ru/forum/message.asp?mid=16950&amp;only
Автор: Holms
Дата: 12.12.01
Best regards,
Андрей Тарасевич
Re[2]: Преобразование указателей
От: Punk Россия  
Дата: 14.12.01 17:30
Оценка:
Здравствуйте Андрей Тарасевич, Вы писали:



АТ>И не должен. Передать массив, декларированный как 'T a[N][M]' в функцию так, чтобы внутри функции его размер не был известен на стадии компиляции, невозможно. Придется организовать эот массив по другому. Посмотри соседние сообщения. Например,

АТ>http://www.rsdn.ru/forum/message.asp?mid=16950&amp;only
Автор: Holms
Дата: 12.12.01



А разве после объявления

int a[2][2];

a не будет типа (double **)?
Re[3]: Преобразование указателей
От: Андрей Тарасевич Беларусь  
Дата: 14.12.01 18:14
Оценка:
Здравствуйте Punk, Вы писали:


АТ>>И не должен. Передать массив, декларированный как 'T a[N][M]' в функцию так, чтобы внутри функции его размер не был известен на стадии компиляции, невозможно. Придется организовать эот массив по другому. Посмотри соседние сообщения. Например,

АТ>>http://www.rsdn.ru/forum/message.asp?mid=16950&amp;only
Автор: Holms
Дата: 12.12.01



P>А разве после объявления


P>int a[2][2];


P>a не будет типа (double **)?


Нет, не будет. С чего бы это? (И почему именно 'double'?)
Best regards,
Андрей Тарасевич
Re[4]: Преобразование указателей
От: Punk Россия  
Дата: 14.12.01 19:48
Оценка:
Здравствуйте Андрей Тарасевич, Вы писали:

АТ>Здравствуйте Punk, Вы писали:



АТ>>>И не должен. Передать массив, декларированный как 'T a[N][M]' в функцию так, чтобы внутри функции его размер не был известен на стадии компиляции, невозможно. Придется организовать эот массив по другому. Посмотри соседние сообщения. Например,

АТ>>>http://www.rsdn.ru/forum/message.asp?mid=16950&amp;only
Автор: Holms
Дата: 12.12.01



P>>А разве после объявления


P>>int a[2][2];


P>>a не будет типа (double **)?


АТ>Нет, не будет. С чего бы это?

а почему тогда работает следующее:
#include<stdio.h>
main()
{ int a[2][2];
int i,j;
a[0][0] = 0;
a[1][0] = 0;
a[0][1] = 0;
a[1][1] = 0;
for(i=0;i<2;i++)
for(j=0;j<2;j++) printf("%d ",*(*(a+i)+j) );

}

???

AT>(И почему именно 'double'?)

int конечно — описался
Re[5]: Преобразование указателей
От: Андрей Тарасевич Беларусь  
Дата: 14.12.01 20:22
Оценка:
Здравствуйте Punk, Вы писали:

P>>>А разве после объявления


P>>>int a[2][2];


P>>>a не будет типа (double **)?


АТ>>Нет, не будет. С чего бы это?

P>а почему тогда работает следующее:
P>#include<stdio.h>
P>main()
P>{ int a[2][2];
P> int i,j;
P> a[0][0] = 0;
P> a[1][0] = 0;
P> a[0][1] = 0;
P> a[1][1] = 0;
P> for(i=0;i<2;i++)
P> for(j=0;j<2;j++) printf("%d ",*(*(a+i)+j) );

P>}


P>???


А почему бы ему не работать?

Смотри по шагам, что означает *(*(a+i)+j):

0. 'a' имеет тип 'int[2][2]'
1. В выражении 'a + i' тип 'a' неявно приводится от типа 'int[2][2]' к типу 'int (*)[2]'. Значение выражения 'a + i' — это указатель типа 'int (*)[2]', который указывает на i-тый подмассив в массиве 'a'.
2. Выражение '*(a + i)' имеет тип 'int[2]'
3. В выражении '*(a + i) + j' снова делается неявное приведение типа: тип 'int[2]' неявно приводится к типу 'int*'. Значение выражения '*(a + i) + j' — это указатель типа 'int*', который указывает на j-тый элемент i-того подмассива в массиве 'a' (т.е. на 'a[i][j]')
4. Выражение '*(*(a + i) + j)' дает нам этот самый 'a[i][j]'

Как видишь никаких 'int**' тут нигде не встречается. Если бы 'a' имело тип 'int**', то мы бы тоде могли записать '*(*(a + i) + j)', но смысл этой записи был бы совершенно иным.
Best regards,
Андрей Тарасевич
Re[6]: Преобразование указателей
От: Юнусов Булат Россия  
Дата: 14.12.01 21:26
Оценка:
Здравствуйте Андрей Тарасевич!
Рад что кто то не спит, а то бессоница, старею что ли
Ежли Punk-у надо передавать в функцию int **ptr
То ему придется отказатся от записей типа int a[2][2]
А расписать инициализацию **ptr ручками
А опосля освободить все что можно

void display(const int nCols, const int nRows, int **p)
{
    for(int y=0; y<nRows; y++)
    {
        for(int x=0; x<nCols; x++)
        {
            printf("%d,",*(*(p+y)+x) ); // Ну ежли так он хочет писать - а пущай и пишет!
        }
        printf("\n");
    }
}


void main(void)
{
    int **p = NULL;
    const int nCols = 8, nRows = 4;
    int x = 0, y = 0;
    
    p = new int* [sizeof(int*) * nRows];
    
    for(y=0; y < nRows; y++)
    {
        p[y] = new int [nCols];
        
        for(int x=0; x < nCols; x++)
        {
            p[y][x] = x;
        }
    }
    
    display(nCols, nRows, p);
    
    for(y=0; y < nRows; y++)
    {
        delete [] p[y];
    }
    
    delete [] p;
}


Вроде работает и в gcc и в msvc
Но как обычно — я элементарные ошибки могу и не заметить

PS
Все это если честно парочно
И когда же народ в stl врубится-влюбится?
Re[7]: Преобразование указателей
От: Punk Россия  
Дата: 14.12.01 21:31
Оценка:
Здравствуйте Юнусов Булат, Вы писали:


ЮБ>Ежли Punk-у надо передавать в функцию int **ptr

ЮБ>То ему придется отказатся от записей типа int a[2][2]
ЮБ>А расписать инициализацию **ptr ручками
ЮБ>А опосля освободить все что можно
Я и так понял, что так не получится.
Просто интересно в чём глюк был
Re[8]: Преобразование указателей
От: Андрей Тарасевич Беларусь  
Дата: 14.12.01 21:44
Оценка: 3 (1)
Здравствуйте Punk, Вы писали:

ЮБ>>Ежли Punk-у надо передавать в функцию int **ptr

ЮБ>>То ему придется отказатся от записей типа int a[2][2]
ЮБ>>А расписать инициализацию **ptr ручками
ЮБ>>А опосля освободить все что можно
P>Я и так понял, что так не получится.
P>Просто интересно в чём глюк был

В общем, вся фишка в том, что тип 'массив' имеет совойство во многих случаях деградировать до типа 'указатель на элемент массива'. Массив 'int a[N]' при этом превращается в указатель 'int*', а массив 'int a[M][N]' превращается в указатель 'int (*)[N]' (а не в 'int**'). Это можно использовать при передаче массива в функцию:


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

int main() 
{ 
  int a[2][2]; 
  a[0][0] = 7; 
  a[0][1] = 4; 
  a[1][0] = 2; 
  a[1][1] = 9; 
  conv(2, a); 
  return 0; 
}


Но переменным при такой передаче будет только первый размер массива. Остальные будут фиксированы.
Best regards,
Андрей Тарасевич
Re: Преобразование указателей
От: Lexey Россия  
Дата: 15.12.01 10:12
Оценка:
Здравствуйте Punk, Вы писали:

P>#include "stdafx.h"


P>void conv(int s, int ** a)

P>{
P> int i, j;
P> for (i = 0; i < s; i++)
P> for (j = 0; j < s; j++)
P> printf("%lf\n", a[i][j] );
P>}


P>int main(int argc, char* argv[])

P>{
P> int a[2][2];
P> a[0][0] = 7;
P> a[0][1] = 4;
P> a[1][0] = 2;
P> a[1][1] = 9;
P> conv(2, (int**)(a));
P> return 0;
P>}

P>Этот код не работает


Помимо неправильной передачи указателя эта вещь не должна работать по еще одной вполне банальной причине: в строке форматирования printf стоит тип double, а передается туда int. Естественно, ничего хорошего из этого не получится.

Вот такой фрагмент работает нормально:

void conv(int s, int * a)
{
int i, j;
for (i = 0; i < s; i++)
for (j = 0; j < s; j++,a++)
printf("%lf\n", (double)*a);
}

int main(int argc, char* argv[])
{
int a[2][2];
a[0][0] = 7;
a[0][1] = 4;
a[1][0] = 2;
a[1][1] = 9;
conv(2, (int *)a);
return 0;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.