Форум программистов, компьютерный форум CyberForum.ru

Указатель на пользовательский тип - C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
05.08.2010, 22:40     Указатель на пользовательский тип #1
Чёто туплю, почему когда передаёшь переменную (например int) параметром через адрес в функцию (параметр - указатель на этот тип), то в теле этой функции для доступа к этой переменной приходится обращаться через указатель как через массив, причём работает только для [0] [1] [2], а дальше выдаёт ошибку. Вообще что значит это? Почему не 1 а 3 элемента и вообще как это так с точки зрения компилятора




p.s. название темы левое, случайно )))
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2295 / 1665 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
05.08.2010, 22:57     Указатель на пользовательский тип #2
darkAngel, для присвоение указываемому объекту используй разыменовение (*) указателя:
C++
1
2
3
void foo(int* pvariable) {
  *pvariable = 5;
}
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
05.08.2010, 23:03  [ТС]     Указатель на пользовательский тип #3
Не, не катит, я использую пользовательский тип
C++
1
2
typedef long int Tlong[2][1000];
Tlong d;
При разименование выдаётся ошибка записи.
Возможен доступ только так: d[0][i][j]
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2295 / 1665 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
05.08.2010, 23:06     Указатель на пользовательский тип #4
darkAngel, еще бы не было ошибки.
C++
1
2
3
4
5
6
7
8
9
10
typedef long int LINT;
 
const int n = 2;
const int m = 1000;
 
LINT d[n][m];
 
void foo(LINT l[n][m]) {
  l[1][456] = 7;
}
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
05.08.2010, 23:26  [ТС]     Указатель на пользовательский тип #5
НЕ, ну от чего ошибка?
Какой резон вообще тогда пользовательский тип делать здесь typedef long int LINT;
Мой тип Tlong означает не long int, а я его использую для представления длинного числа с дробной частью, аименно двумерный массив.
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2295 / 1665 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
05.08.2010, 23:55     Указатель на пользовательский тип #6
darkAngel, я знаю, что означает твой тип, дак вот - не надо так извращатся.
Цитата Сообщение от darkAngel Посмотреть сообщение
НЕ, ну от чего ошибка?
Так пробовал:
C++
1
2
3
void foo(Tlong* l) {
  (*l)[2][4] = 6;
}
?

Добавлено через 24 минуты
darkAngel, кстати, указатель здесь не нужен.
C++
1
2
3
void foo(Tlong l) {
  l[2][4] = 6;
}
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 00:02     Указатель на пользовательский тип #7
CyBOSSeR, указатель не нужен-то, но, наверное, было бы эффективнее передавать по константной ссылке, не?..
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2295 / 1665 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
06.08.2010, 00:09     Указатель на пользовательский тип #8
Demihalf, нет - двумерный массив будет передан как указатель на первый элемент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
const int n = 2;
const int m = 2;
 
void foo(int matrix[n][m]) {
  std::cout << *reinterpret_cast<int*>(matrix) << std::endl;
}
 
int main() {
  int matrix[n][m] = {
    {1, 2},
    {3, 4},
  };
 
  foo(matrix);
}
Результат: http://codepad.org/jcbGImyM
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 00:11     Указатель на пользовательский тип #9
CyBOSSeR, а, ну да, я подумал, что Tlong - класс
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2295 / 1665 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
06.08.2010, 00:12     Указатель на пользовательский тип #10
Demihalf, не удивительно, я уже говорил ТС, что такое использование typedef - извращение.
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 00:18     Указатель на пользовательский тип #11
CyBOSSeR, я полагаю, это влияние Паскаля...
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
06.08.2010, 09:26  [ТС]     Указатель на пользовательский тип #12
Demihalf, не удивительно, я уже говорил ТС, что такое использование typedef - извращение.
Я вообще этим пользую редко. Тогда для чего нужен пользовательский тип?

CyBOSSeR, я полагаю, это влияние Паскаля...
А Паскаль тут вообще причём?
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 10:49     Указатель на пользовательский тип #13
darkAngel, пользовательским типом обычно называют именованные класс, структуру, объединение, перечисление. А typedef в Си++ - чаще всего псевдоним для существующего типа. Например:

C++
1
2
int*(*funcp)(double, int); /* Указатель на функцию, принимающую double и int и возвращающую указатель на int. */
int* (*func(int a, int b))(double, int)  /* Прототип функции с именем func, принимающей 2 параметра int и вовращающей указатель на функцию, принимающую double и int и возвращающую указатель на int. */
Весело. А теперь, как это будет выглядеть при использовании typedef:

C++
1
2
3
4
5
typedef int*(*fptr)(double, int);  /* Объявление псевдонима типа "указатель на функцию  принимающую double и int и возвращающую указатель на int." */
 
fptr funcp; /* То же объявление указателя, что и в примере без typedef */
 
fptr func(int a, int b); /*Тот же прототип, что и в примере без typedef */
Чувствуете разницу?

Добавлено через 7 минут
А Паскаль вот причем:
Описание массива в Паскале. В языке Паскаль тип массива задается с использованием специального слова array (англ. – массив), и его объявление в программе выглядит следующим образом:
Pascal
1
Type < имя _ типа >= array [ I ] of T;
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
06.08.2010, 12:22  [ТС]     Указатель на пользовательский тип #14
ну а чем хуже пример:
C++
1
2
typedef long int Tlong[2][1000];
Tlong d, c, b, a ,e;
и
C++
1
long int a[2][1000],d[2][1000],c[2][1000],b[2][1000],e[2][1000];
Добавлено через 29 секунд
я знаю паскаль.



Добавлено через 1 час 30 минут
Кстати не пойму, как теперь указатель сдлеать на тип Tlong
Так не катит:
Tlong *a = &d;
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 12:37     Указатель на пользовательский тип #15
darkAngel, вообще, Tlong - уже тип указателя. Имя массива указвает на его первый элемент. И у меня все вполне компилится.

C
1
2
3
4
5
6
7
8
9
10
11
  #include <stdio.h>
  
  typedef long int Tlong[2][1000];
 
  int main( void )
  { 
     Tlong a;
     Tlong *b = &a;  
  
   return 0;
  }
Только здесь уже получается тройной указатель...
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
06.08.2010, 13:04  [ТС]     Указатель на пользовательский тип #16
Не, у меня такая ситуация, в теле функции:
C
1
2
3
4
void ddd(Tlong a)
{
   Tlong *b = &a;
}
Вне функции всё ОК, а так выдаёт ошибку Cannot convert 'long ( * *)[1000]' to 'long ( *)[2][1000]'

Добавлено через 1 минуту
ппочему-то одно измерение массива пропадает ( * *)[1000] и ( *)[2][1000]'
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 13:44     Указатель на пользовательский тип #17
darkAngel, хм. Можно извратиться и попробовать так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef long int Tlong[2][1000];
  
void ddd(long int **c)
{
    long int ***b = &c;
}
 
int main( void )
{ 
    Tlong a;
    long int **b = new long int*[2];
    for (int i = 0; i < 2; i++) {
        b[i] = new long int[1000];
        
        for (int j = 0; j < 1000; j++) {
            b[i][j] = a[i][j];
        }
    }
     
    ddd(b);
  
    return 0;
}
А вообще, было бы проще сделать отдельный класс, в который инкапсулировать массив.
darkAngel
Технофашист
211 / 192 / 4
Регистрация: 11.03.2009
Сообщений: 850
06.08.2010, 22:26  [ТС]     Указатель на пользовательский тип #18
void ddd(long int **c)
Да как бы всё с этого и началось в начале темы )) что указатель на Tlong был в параметре. А CyBOSSeR посоветовал просто передавать.

А вообще, было бы проще сделать отдельный класс, в который инкапсулировать массив.
Ага, у же сам так подумал. Да и операции можно перегрузить. Ладно спасибо за помощь.

Добавлено через 3 часа 50 минут
Теперь проблема с перезагрузкой операций. Вот (код не дословный, только основные моменты, чтобы передать суть):

Вот у меня пусть есть класс:
C++
1
2
3
4
5
class Long
{
   long int lng[2][1000];  
   //конструкторы и методы, не пишу
};
Есть 3 объекта:
C++
1
Long a, b, c;
Вот я прегружаю присваивание:
C++
1
2
3
4
5
6
7
Long& operator = (Long &ch)
{
   for (int i=0; i<1000; i++) {
      lng[0][i] = ch.lng[0][i];
      lng[1][i] = ch.lng[1][i];
   }
   return *this;
}

Вот теперь внимание здесь - прегрузка сложения:
C++
1
2
3
4
5
6
Long& operator +(Long chB)
{
   Long *chR = new Long;          
   //....тут идёт сложение, что-то типа: chR->lng[0][0] = lng[0][0] + chB.lng[0][0]
   return *chR;
}

Ну и результат:
c = a + b;
Работает всё ровно, но у меня закрались сомнения. В теле перегрузки сложения я выделал память под новый объект, где хранился результат и возвращал ссылку на него. После шло присваивание, а точнее копирование в переменную C данных по ссылке, полученной из сложения.
Дак получается, что память, куда указывает ссылка, остаётся занятой и превращается в мусор. Как мне быть? очищать её в теле перегрузки присваивания в конце? Тогда получается, если я просто буду присваивать c = b, то будет удаляться нужный объект b.
Надеюсь понятно выразил мысли
Demihalf
Унылый школьник
 Аватар для Demihalf
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 22:39     Указатель на пользовательский тип #19
darkAngel, чтобы проверить утечки памяти можно использовать утилиту valgrind или что-нибудь подобное.

Да, и еще, как мне кажется, лучше будет заменить массив на stl'шный vector

Добавлено через 5 минут
Какой-то бессмысленный совет я дал насчет valgrind... Вы зачем в куче память для временного объекта выделяете? Если его объявить в стеке, проблема сама исчезнет.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.08.2010, 03:34     Указатель на пользовательский тип
Еще ссылки по теме:

Реализовать пользовательский тип "Сотрудник" (структуры) C++
Определить пользовательский тип (структуру), включающий в себя строку, целое число C++
C++ Шаблон класса. Пользовательский тип данных
Visual C++ Пользовательский тип переменной с произвольной размерностью
C++ Найти факториал, используя пользовательский тип

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
abiprofi
 Аватар для abiprofi
48 / 48 / 2
Регистрация: 04.08.2010
Сообщений: 110
07.08.2010, 03:34     Указатель на пользовательский тип #20
С помощью ключевого слова typedef можно определить новое имя типа данных. Новый тип при этом не создается!
Используя оператор typedef, можно повысить наглядность программы, но нельзя создать новый тип данных!
typedef long int Tlong[2][1000], воспринимается компилятором как long int Tlong[2][1000]
C++
1
2
3
Tlong a;
a[0][0] = 0;//это верно
a[1][999] = 5;//это верно
Добавлено через 1 час 7 минут
Объявление:
C++
1
typedef long int Tlong[2][1000];
Без всяких извращений
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//---------------------------------------------------------------------------
//В .h
 void __fastcall Mytest(long int c[][1000]);
//---------------------------------------------------------------------------
//В .cpp
void __fastcall TForm1::Button5Click(TObject *Sender)
{
 Tlong a;
 a[0][0] = 0;
 a[1][999] = 5;
 
 Memo1->Lines->Add(FloatToStr(a[1][999]));//5
 Mytest(a);
 Memo1->Lines->Add(FloatToStr(a[1][999]));//11
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Mytest(long int c[][1000])
{
 c[1][999] = 11;//это верно
}
//---------------------------------------------------------------------------
Yandex
Объявления
07.08.2010, 03:34     Указатель на пользовательский тип
Ответ Создать тему
Опции темы

Текущее время: 10:24. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru