Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
10 / 10 / 4
Регистрация: 14.01.2010
Сообщений: 80

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

16.11.2012, 12:46. Показов 3657. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Недавно начал изучать Си, перешел с Delphi.
Много непонятного и пока процесс идет медленно. Накачал литературы, буду изучать)
Щас хотелось бы узнать как решить следующую задачу:

Пишу DLL, в ней есть экспортируемая функция:
Code
1
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
Code
1
2
char  temp[1024];
strcpy(temp,(char *)in_data)
и смог использовать, может есть лучше способ?

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

Спасибо.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.11.2012, 12:46
Ответы с готовыми решениями:

Через указатели на указатели посчитать сумму двух чисел и записать в третье
1. Через указатели на указатели посчитать сумму двух чисел и записать в третье. 2. Написать примитивный калькулятор, пользуясь только...

Почему Лафоре использует указатели на указатели, вместо обмена значениями указателей?
Доброго времени суток! Задался теоретическим вопросом. Читал пример из книги Лафоре ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++,...

Используя нетипизированные указатели и указатели на подпрограммы обобщить сортировку пузырьком
Смысл задания в том, что нужно отсортировать массив структур из 3х полей по сумме координат есть структура struct XYZ{ ...

17
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
16.11.2012, 12:56
Цитата Сообщение от Duss Посмотреть сообщение
Указатель на указатель
это называется двойной указатель.
Цитата Сообщение от Duss Посмотреть сообщение
для чего такой может использоваться?
Ну во-первых через указатели на нулевые элементы реализуются массивы. А если элементы массива сами массивы? Получается, что массивы-элементы реализуются через указатели, а сам массив - массив указателей, но тоже реализуется через указатель. На что? Только на указатель же. Во-вторых через указатели реализуются изменяемые в самой функции параметры. А если при этом сам параметр - указатель? Или массив? Вот и получается двойной. Но тогда он может быть зщаменён ссылкой на указатель, да и вообще изменяемые параметры могут реализовываться ссылками вместо указателей.

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

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

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

Добавлено через 6 минут
Цитата Сообщение от Duss Посмотреть сообщение
И мне нужно перевести in_data или temp перевести в LPCSTR,
зачем?
1
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
16.11.2012, 13:21
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 будет указывать на динамически выделенный массив.
1
10 / 10 / 4
Регистрация: 14.01.2010
Сообщений: 80
16.11.2012, 13:21  [ТС]
Ок, т.е. unsigned char *in_data - это массив чаров (строка),
а unsigned char **out_data это массив массивов чаров (массив строк).

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

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

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

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

Добавлено через 2 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
Передавай, как есть, это одно и то же.
LogsOut: невозможно преобразовать параметр 3 из 'unsigned char *' в 'LPCSTR'
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
16.11.2012, 13:48
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. явное преобразование
1
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
16.11.2012, 13:49
Тогда передай
C++
1
(char *)in_data
, или
C++
1
(LPCSTR) in_data
.
1
10 / 10 / 4
Регистрация: 14.01.2010
Сообщений: 80
16.11.2012, 16:33  [ТС]
Во многом разобрался.
out_data - объявил как


Code
1
2
3
char buffer[256];
char *res = buffer;
int len;
Code
1
2
3
4
res = "wwwww";
out_data =  (unsigned char **)&res;
len = sizeof(out_data);
out_size = &len;
Переменные объявлены глобально, чтобы после выполнения функции они не уничтожались.
Но после вызова функции получаю эти значения пустыми.
Функция находится в ДЛЛ, вызываю ее не из самой длл.
Может глобальные переменные нужно где-то в паблике объявить?
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
16.11.2012, 16:50
Цитата Сообщение от 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;
. Обрати внимание, оба указателя функция получает, а не передаёт. В память по адресу из полученного двойному она присваивает простой указатель, а в память по адресу из полученного простого указателя пишет число.
0
10 / 10 / 4
Регистрация: 14.01.2010
Сообщений: 80
16.11.2012, 17:00  [ТС]
В том то и дело- вызывающая программа не моя.
Я к ней могу написать DLL плагин и подключиться через API и вызвать через него функцию MtSrvManagerProtocol
Т.е. спровоцировать ее вызов и получить результаты.

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

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

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

MtSrvManagerProtocol

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


Code
1
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 - обычная автоматическая переменная, только у тебя от неё не идентификатор, а только адрес и для записи нужна косвенная адресация. Это
Code
1
*out_data=new char [32];
и есть создание в куче.
Да, про кучу я почитал немного так тоже пробовал.
ругается:

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

Добавлено через 2 минуты
я еще хотел res создать в куче
Code
1
res=new char [256];
а в out_data указатель на res отправить.
Code
1
ut_data =  (unsigned char **)&res;
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
17.11.2012, 22:08
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 файле
Да. Но она уже с ним скомпилена. И в ней уже не учтены те переменные, которые ты придумал после её компиляции. Синтаксис вызова учтён, а глобальных переменных библиотеки она не знает, так как они не учтены и не могли быть учтены при написании самой программы. Твоя библиотека - другая программа и о ней вызывающая не знает ничего, кроме синтаксиса вызова использованных в вызывающей программе функций из твоей библиотеки.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.11.2012, 22:08
Помогаю со студенческими работами здесь

Есть три переменные. Используя указатели на указатели, поменять значение максимальной и минимальной переменной
Мой код. #include &lt;iostream&gt; #include &lt;stdlib.h&gt; #include&lt;iomanip&gt; using namespace std; void min_max(int*pa, int*pb,...

Указатели на указатели с числами. Почему можно присвоить число в 4-ый элемент, если массив из 2 элементов?
Есть массив int **mas; mas=new int*; // выделил место под пять строк, верно ? mas=new int;// выделил для первой строки матрицы два...

Отсортировать массив и вывести на экран (массивы и указатели на указатели)
Даны массивы F-фамилий студентов и S-результаты сессии (5 оценок) , причем s- результат сессии F студента. Отсортировать массив S по...

Указатели на указатели: для чего они могут понадобятся?
Изучаю C++, дошёл до указателей на указатели. Там пишут что эта тема не обязательна. Для чего они могут понадобятся?

Указатели на указатели, как правильно разыменовать, где ошибка?
1)Есть класс: Shape - абстрактный; у него есть классы наследники: Circle, Triangle. 2)Eсть контейнер: vector &lt;Shape*&gt; Scontainer;...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru