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

Указатели и указатели на указатели, а также типы данных - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.91
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 12:46     Указатели и указатели на указатели, а также типы данных #1
Недавно начал изучать Си, перешел с Delphi.
Много непонятного и пока процесс идет медленно. Накачал литературы, буду изучать)
Щас хотелось бы узнать как решить следующую задачу:

Пишу DLL, в ней есть экспортируемая функция:
Код
void APIENTRY MtSrvManagerProtocol(ULONG ip, UserInfo *us, unsigned char *in_data, int in_size,unsigned char **out_data,int *out_size)
Что за тип **out_data ? Указатель на указатель? для чего такой может использоваться? и самое главное как его заполнить данными?

char *in_data
с горем пополам перевел в char
Код
char  temp[1024];
strcpy(temp,(char *)in_data)
и смог использовать, может есть лучше способ?

И мне нужно перевести in_data или temp перевести в LPCSTR, как это лучше сделать?

Спасибо.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.11.2012, 12:46     Указатели и указатели на указатели, а также типы данных
Посмотрите здесь:

C++ Указатели, работа с динамическими структурами данных и динамические списки, стеки
Указатели и динамические структуры данных C++
Указатели и динамические структуры данных C++
Динамически струтуры данных. Даны указатели P1 и P2 на вершины двух непустых стеков... C++
C++ Объявите указатели на следующие типы int, char, double - проинициализируйте их, выведите их значения на экран.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 12:56     Указатели и указатели на указатели, а также типы данных #2
Цитата Сообщение от Duss Посмотреть сообщение
Указатель на указатель
это называется двойной указатель.
Цитата Сообщение от Duss Посмотреть сообщение
для чего такой может использоваться?
Ну во-первых через указатели на нулевые элементы реализуются массивы. А если элементы массива сами массивы? Получается, что массивы-элементы реализуются через указатели, а сам массив - массив указателей, но тоже реализуется через указатель. На что? Только на указатель же. Во-вторых через указатели реализуются изменяемые в самой функции параметры. А если при этом сам параметр - указатель? Или массив? Вот и получается двойной. Но тогда он может быть зщаменён ссылкой на указатель, да и вообще изменяемые параметры могут реализовываться ссылками вместо указателей.

Добавлено через 1 минуту
Цитата Сообщение от Duss Посмотреть сообщение
Что за тип **out_data ?
У тебя нет такого типа.
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 12:57  [ТС]     Указатели и указатели на указатели, а также типы данных #3
Что за тип **out_data ?
У тебя нет такого типа.
Да, в смысле unsigned char **out_data.
Т.е. что такое unsigned char я понимаю, меня интересует зачем **.
А для чего нужен двойной указатель? Т.е. он указывает на память, в которой хранится указатель на unsigned char ?
Не совсем понимаю смысл этого.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 13:09     Указатели и указатели на указатели, а также типы данных #4
Цитата Сообщение от Duss Посмотреть сообщение
char *in_data
с горем пополам перевел в char
перекосячил. Указатель в ча не переводится.

Добавлено через 3 минуты
Цитата Сообщение от Duss Посмотреть сообщение
char *temp[1024];
strcpy(temp,(char *)in_data)
Зачем? У тебя уже указатель на char. Зачем ещё один? К тому же это опасно переполнением массива, так как автоматический массив резервируется конкретного размера, а указатель подразумевает динамический, размер которого не известен.

Добавлено через 34 секунды
Цитата Сообщение от Duss Посмотреть сообщение
и смог использовать, может есть лучше способ?
Нет худшего.

Добавлено через 6 минут
Цитата Сообщение от Duss Посмотреть сообщение
И мне нужно перевести in_data или temp перевести в LPCSTR,
зачем?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
16.11.2012, 13:21     Указатели и указатели на указатели, а также типы данных #5
C++
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
//Чтобы функция могла менять переменную, нужно передать ее в эту функцию по указателю или по ссылке. 
//Будем рассматривать случай с указателями:
 
void SetFive(int* ptr)
{
  *ptr = 5;
}
 
// в коде:
int value = 0;
SetFive(&value);
// вот тут значение value будет равно 5
 
 
 
// Теперь, если функция должна изменять указатель, то в функцию нужно передать указатель на указатель:
void Allocate(char** ptr)
{
  *ptr = new char[10];
}
 
// в коде:
char* p = 0;
Allocate(&p);
// вот тут p будет указывать на динамечески выделенный массив. p != 0;
 
 
//Аналогия с интом еще более наглядна, если сделать тайпдеф для указателя:
typedef char* CharPtr;
 
// в случае с интом аргумент имел тип int*,  а в нашем случае - CharPtr*
// т.е. сперва идет имя типа, а потом звездочка
void Allocate(CharPtr* ptr)
{
  // в случае с интом было *ptr = 5, а в этом случае так:
  *ptr = new char[10];
}
 
//в коде тоже все похоже на случай с интом.
//сперва объявляется переменная типа CharPtr и чтобы она изменилас,
//в функцию передается ее адрес
CharPtr ptr = 0;
Allocate(&ptr);
// тут ptr будет указывать на динамически выделенный массив.
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 13:21  [ТС]     Указатели и указатели на указатели, а также типы данных #6
Ок, т.е. unsigned char *in_data - это массив чаров (строка),
а unsigned char **out_data это массив массивов чаров (массив строк).

Цитата Сообщение от taras atavin Посмотреть сообщение
зачем?
Есть функция записи в лог, она принимает LPCSTR, я бы хотел перевести char *in_data в LPCSTR и посмотреть что я получил то же что отправил или что-то другое)

Как мне заполнить out_data данными? в Delphi можно было указать размеры массива, если он безразмерный или размер определялся при объявлении.
Например я хочу в out_data засунуть 1 строчку
Код
 out_data[0] = in_data;
в принципе проходит, также заполняю out_size
Код
out_size[0] =in_size;
этого достаточно? Компилятор поймет что элемента out_data[1] нет или там может быть мусор?
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 13:30     Указатели и указатели на указатели, а также типы данных #7
Цитата Сообщение от Duss Посмотреть сообщение
Есть функция записи в лог, она принимает LPCSTR, я бы хотел перевести char *in_data в LPCSTR и посмотреть что я получил то же что отправил или что-то другое)
Передавай, как есть, это одно и то же.

Добавлено через 3 минуты
Цитата Сообщение от Duss Посмотреть сообщение
out_size[0] =in_size;
этого достаточно? Компилятор поймет что элемента out_data[1] нет или там может быть мусор?
Нет. Меня смущает out, возможно это выходные, то есть изменяемые параметры, тогда out_data - простой массив cahrов, а не массив массивов, а out_size - вообще не массив. Но в любом случае запись чего либо в нулевой элемент не говорит об остальных элементах.
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 13:41  [ТС]     Указатели и указатели на указатели, а также типы данных #8
Цитата Сообщение от taras atavin Посмотреть сообщение
Нет. Меня смущает out, возможно это выходные, то есть изменяемые параметры, тогда out_data - простой массив cahrов, а не массив массивов, а out_size - вообще не массив. Но в любом случае запись чего либо в нулевой элемент не говорит об остальных элементах.
Да, так и есть.
В ин я получаю строку, в аут могу отдать строку, в некоторых случаях массивы строк.
Т.е. out_data должна быть массивом строк.
Т.к. это DLL я должен передать размер всего этого дела, для этого служит out_size

Добавлено через 1 минуту
DU Спасибо за примеры, вкуривю.

Добавлено через 2 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
Передавай, как есть, это одно и то же.
LogsOut: невозможно преобразовать параметр 3 из 'unsigned char *' в 'LPCSTR'
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
16.11.2012, 13:48     Указатели и указатели на указатели, а также типы данных #9
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
// Ошибка потому что
typedef char CHAR;
typedef const CHAR* LPCSTR;
//т.е. 
LPCSTR == const char*
 
//неявно преобразовывать unsigned char* в char* нельзя. это раные типы.
 
 
  unsigned char* p1 = 0;
  char* p2 = 0;
  p2 = p1; // ошибка
  p2 = (char*)p1; // ok. явное преобразование
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 13:49     Указатели и указатели на указатели, а также типы данных #10
Тогда передай
C++
1
(char *)in_data
, или
C++
1
(LPCSTR) in_data
.
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 16:33  [ТС]     Указатели и указатели на указатели, а также типы данных #11
Во многом разобрался.
out_data - объявил как


Код
char buffer[256];
char *res = buffer;
int len;
Код
res = "wwwww";
out_data =  (unsigned char **)&res;
len = sizeof(out_data);
out_size = &len;
Переменные объявлены глобально, чтобы после выполнения функции они не уничтожались.
Но после вызова функции получаю эти значения пустыми.
Функция находится в ДЛЛ, вызываю ее не из самой длл.
Может глобальные переменные нужно где-то в паблике объявить?
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 16:50     Указатели и указатели на указатели, а также типы данных #12
Цитата Сообщение от Duss Посмотреть сообщение
Переменные объявлены глобально, чтобы после выполнения функции они не уничтожались.
Но после вызова функции получаю эти значения пустыми.
Функция находится в ДЛЛ, вызываю ее не из самой длл.
Может глобальные переменные нужно где-то в паблике объявить?
Паблик в глобале. Капец! Это же не член класса, а память другой программы, она должна быть экспортируемой. А лучше создавай в куче.

Добавлено через 8 минут
Причём, даже так: вызывающая программа:
C++
1
2
3
4
5
6
ULONG ip;
UserInfo us;
unsigned char in_data[16];
unsigned char *out_data;
int out_size;
MtSrvManagerProtocol (ip, &us, in_data, 16, &out_data. &outsize)
, функция:
C++
1
2
*out_data=new char [32];
*outsize=32;
. Обрати внимание, оба указателя функция получает, а не передаёт. В память по адресу из полученного двойному она присваивает простой указатель, а в память по адресу из полученного простого указателя пишет число.
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 17:00  [ТС]     Указатели и указатели на указатели, а также типы данных #13
В том то и дело- вызывающая программа не моя.
Я к ней могу написать DLL плагин и подключиться через API и вызвать через него функцию MtSrvManagerProtocol
Т.е. спровоцировать ее вызов и получить результаты.

Как мне засунуть переменные out в кучу?
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 17:04     Указатели и указатели на указатели, а также типы данных #14
Тогда весь этот синтаксис там уже соблюдён.
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 17:06  [ТС]     Указатели и указатели на указатели, а также типы данных #15
т.е. мне достаточно у себя в DLL объявить переменные глобально, чтобы у вызывающей программы был к ним доступ?
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
16.11.2012, 17:07     Указатели и указатели на указатели, а также типы данных #16
Цитата Сообщение от Duss Посмотреть сообщение
Как мне засунуть переменные out в кучу?
Одну переменную. size - обычная автоматическая переменная, только у тебя от неё не идентификатор, а только адрес и для записи нужна косвенная адресация. Это
Цитата Сообщение от taras atavin Посмотреть сообщение
C++
1
*out_data=new char [32];
и есть создание в куче.

Добавлено через 1 минуту
Цитата Сообщение от Duss Посмотреть сообщение
.е. мне достаточно у себя в DLL объявить переменные глобально, чтобы у вызывающей программы был к ним доступ?
Нет. Во-первых ты можешь только экспортировать, а не глобалить. А во-вторых откуда вызывающая программа узнает, как эти переменные зовут?
Duss
10 / 10 / 0
Регистрация: 14.01.2010
Сообщений: 77
16.11.2012, 17:20  [ТС]     Указатели и указатели на указатели, а также типы данных #17
[size="1"][color="grey"]откуда вызывающая программа узнает, как эти переменные зовут?[/QUOTE]

К вызывающей программе есть мануал, в нем сказано, что она вызывает функцию

MtSrvManagerProtocol

Синтаксис описан в .h файле


Код
void APIENTRY MtSrvManagerProtocol(ULONG ip, UserInfo *us, unsigned char *in_data, int in_size,unsigned char **out_data,int *out_size)
Добавлено через 6 минут
Цитата Сообщение от taras atavin Посмотреть сообщение
Одну переменную. size - обычная автоматическая переменная, только у тебя от неё не идентификатор, а только адрес и для записи нужна косвенная адресация. Это
Код
*out_data=new char [32];
и есть создание в куче.
Да, про кучу я почитал немного так тоже пробовал.
ругается:

отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
и
инициализация: невозможно преобразовать 'char *' в 'int *'

Добавлено через 2 минуты
я еще хотел res создать в куче
Код
res=new char [256];
а в out_data указатель на res отправить.
Код
ut_data =  (unsigned char **)&res;
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.11.2012, 22:08     Указатели и указатели на указатели, а также типы данных
Еще ссылки по теме:

Указатели и структура данных C++
Запись данных в динамический массив через указатели C++
Непонятный синтаксис, указатели, типы, ссылки C++

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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
17.11.2012, 22:08     Указатели и указатели на указатели, а также типы данных #18
C++
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
include <iostrem.h>
int main ()
{
 char s1[16]="qwer";
 char *s2;
 char *s3;
 char *s4;
 int i;
 s2=s1; // Допустимо, присваивается адрес нулевого элемента.
 s3=new char [16];
 for (i=15; i>=0; --i)
 {
  s3[i]=s1[i]; // Допустимо, s3[i] - i-тый элемент динамического массива, на начало которого указывает s3.
 }
 s4=new char [16];
 for (i=15; i>=0; --i)
 {
  *(s3+i)=*(s1+i); // Не проверял, но вроде бы допустимо, (s1+i) - i-тый элемент "динамического" массива, на начало которого указывает s1.
 }
 std::cout<<s1<<std::endl; // Выводит qwer
 std::cout<<s2<<std::endl; // Выводит qwer
 std::cout<<s3<<std::endl; // Выводит qwer
 std::cout<<s4<<std::endl; // Не проверял, но должно быть выведено qwer
 delete [] s3;
 delete [] s4;
 return 0;
}
Вообще, массив и указатель на его нулевой элемент - одно и тоже, на сколько мне известно, иначе "думает" только sizeof: в примере sizeof (s1) равен 16, то есть размеру самого массива, а sizeof (s2), sizeof (s3) и sizeof (s4) равны размеру указателя.

Добавлено через 1 минуту
Цитата Сообщение от Duss Посмотреть сообщение
отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
и
инициализация: невозможно преобразовать 'char *' в 'int *'
Исходник в студию.

Добавлено через 3 минуты
Цитата Сообщение от Duss Посмотреть сообщение
а в out_data указатель на res отправить.
C++
1
ut_data = *(unsigned char **)&res;
Нельзя: значение ut_data есть адрес простого указателя на char, оно не может быть передано вызывающей программе, надо в память по этому адресу записать другой адрес - значение простого указателя на char, оно же адрес нуль-терминальной строки.

Добавлено через 1 минуту
Запомни: сам параметр может быть возвращён вызывающей программе только в том случае, если он ссылка. Если же это указатель, то вернуть информацию можно только через память по адресу, равному полученному значению параметра.

Добавлено через 2 минуты
Цитата Сообщение от Duss Посмотреть сообщение
К вызывающей программе есть мануал, в нем сказано, что она вызывает функцию
MtSrvManagerProtocol
Синтаксис описан в .h файле
Да. Но она уже с ним скомпилена. И в ней уже не учтены те переменные, которые ты придумал после её компиляции. Синтаксис вызова учтён, а глобальных переменных библиотеки она не знает, так как они не учтены и не могли быть учтены при написании самой программы. Твоя библиотека - другая программа и о ней вызывающая не знает ничего, кроме синтаксиса вызова использованных в вызывающей программе функций из твоей библиотеки.
Yandex
Объявления
17.11.2012, 22:08     Указатели и указатели на указатели, а также типы данных
Ответ Создать тему
Опции темы

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