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

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
darkAngel
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
#1

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

05.08.2010, 22:40. Просмотров 1700. Ответов 23
Метки нет (Все метки)

Чёто туплю, почему когда передаёшь переменную (например int) параметром через адрес в функцию (параметр - указатель на этот тип), то в теле этой функции для доступа к этой переменной приходится обращаться через указатель как через массив, причём работает только для [0] [1] [2], а дальше выдаёт ошибку. Вообще что значит это? Почему не 1 а 3 элемента и вообще как это так с точки зрения компилятора




p.s. название темы левое, случайно )))
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.08.2010, 22:40     Указатель на пользовательский тип
Посмотрите здесь:

Пользовательский тип - Visual C++
Как задать пользовательский тип в С++? То есть аналог type

Пользовательский тип данных для C - C++
Помогите пожалуйста создать пользовательский тип данных для языка C, так как мне не хватает обычных....

Найти факториал, используя пользовательский тип - C++
Найти факториал n!=1*2*3...*n решить через классы,

ostream_iterator, copy и пользовательский тип данных - C++
Здравствуйте. #include<iostream> #include<fstream> #include<string> #include<sstream> #include<set> #include<vector> ...

Пользовательский тип переменной с произвольной размерностью - Visual C++
Можно ли создать тип,переменные которого имеют,к примеру, разрядность 99 бит Например,если int - 32 бит,то нужно int99 бит По заданию...

Шаблон класса. Пользовательский тип данных - C++
Всем привет. Помогите с кодом. Не получается сделать пользовательский тип данных. Создаю объект в главной функции, но выдаёт ошибку если...

Наследование - не могу определить пользовательский тип данных - C++
Доброго вечера! Я запутался с наследованием. Определил класс Dlina, состоящий из метров и сантиметров, в котором перегрузил операцию...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CyBOSSeR
Эксперт C++
2299 / 1669 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
05.08.2010, 22:57     Указатель на пользовательский тип #2
darkAngel, для присвоение указываемому объекту используй разыменовение (*) указателя:
C++
1
2
3
void foo(int* pvariable) {
  *pvariable = 5;
}
darkAngel
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
05.08.2010, 23:03  [ТС]     Указатель на пользовательский тип #3
Не, не катит, я использую пользовательский тип
C++
1
2
typedef long int Tlong[2][1000];
Tlong d;
При разименование выдаётся ошибка записи.
Возможен доступ только так: d[0][i][j]
CyBOSSeR
Эксперт C++
2299 / 1669 / 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
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
05.08.2010, 23:26  [ТС]     Указатель на пользовательский тип #5
НЕ, ну от чего ошибка?
Какой резон вообще тогда пользовательский тип делать здесь typedef long int LINT;
Мой тип Tlong означает не long int, а я его использую для представления длинного числа с дробной частью, аименно двумерный массив.
CyBOSSeR
Эксперт C++
2299 / 1669 / 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
Унылый школьник
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 00:02     Указатель на пользовательский тип #7
CyBOSSeR, указатель не нужен-то, но, наверное, было бы эффективнее передавать по константной ссылке, не?..
CyBOSSeR
Эксперт C++
2299 / 1669 / 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
Унылый школьник
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 00:11     Указатель на пользовательский тип #9
CyBOSSeR, а, ну да, я подумал, что Tlong - класс
CyBOSSeR
Эксперт C++
2299 / 1669 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
06.08.2010, 00:12     Указатель на пользовательский тип #10
Demihalf, не удивительно, я уже говорил ТС, что такое использование typedef - извращение.
Demihalf
Унылый школьник
126 / 60 / 3
Регистрация: 06.11.2009
Сообщений: 354
06.08.2010, 00:18     Указатель на пользовательский тип #11
CyBOSSeR, я полагаю, это влияние Паскаля...
darkAngel
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
06.08.2010, 09:26  [ТС]     Указатель на пользовательский тип #12
Demihalf, не удивительно, я уже говорил ТС, что такое использование typedef - извращение.
Я вообще этим пользую редко. Тогда для чего нужен пользовательский тип?

CyBOSSeR, я полагаю, это влияние Паскаля...
А Паскаль тут вообще причём?
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
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
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
Унылый школьник
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
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
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
Унылый школьник
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
Технофашист
214 / 195 / 4
Регистрация: 11.03.2009
Сообщений: 860
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
Унылый школьник
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     Указатель на пользовательский тип
Еще ссылки по теме:

STL контейнер stack, содержит пользовательский тип данных - C++
Ошибки при компиляции следующего кода: Файл element.h #ifndef ELEMENT_H #define ELEMENT_H #include &lt;iostream&gt; using namespace...

Определить пользовательский тип (структуру), включающий в себя строку, целое число - C++
Продолжение: указатель на байт, указатель на число с плавающей точкой. Определить динамический массив из N полученных структур. Как это...

указатель на неопределенный тип - C++
Можете привести пример простой программы с этим указателем void* p; Я что-то не могу придумать с ним можно сделать..

Указатель на тип данны - C++
Если я правильно понял то: struct Vector{ int x; int y; }Ve; Vector - тип данных такой же как int только самописный, Ve...

Указатель и его неопределённый тип - C++
struct SAI_BuMa { int number_BuMa; int counter_BuMa; }; AI.style.pointer = new SAI_BuMa; IF_data_AI &gt;&gt; tmp; ...


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

Или воспользуйтесь поиском по форуму:
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     Указатель на пользовательский тип
Ответ Создать тему
Опции темы

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