Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Указатели...Я просто фигею...  (Прочитано 22143 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
DaSharm
Гость
« : 23-01-2005 14:01 » 

Понял суть работы с указателями. Но на практике просто фигею. Что оно такое:


char a;
void SetT(char *T)
{
      T[0]='a';
           T[1]='b';
}





int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

    SetT(&a);

   MessageBox(0,&a,NULL,0);
   return 0;
}

ПОЧЕМУ T[0]='a' и  T[1]='b' так без ошибок записались?Не понял Ведь память под них я не выделял!!! По идее там должен был быть 0 размерный массив, а он как-то сам по себе увеличивается. Мне оч. это все портит картину об указателях... Помогите, обясните что это такое...
        
« Последнее редактирование: 19-12-2007 19:53 от Алексей1153++ » Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #1 : 23-01-2005 14:33 » 

DaSharm, это неправильное использование указателей. Указатель не означает наличие какого либо массива. За этим должен следить программист. Если у тебя область памяти по указателю инициализирована под хранение одного символа, буть добр не портить неинициализированную область. Иначе рискуешь получить вместо ожидаемых данных телефон чьей-то бабушки. Если такое представление об указателях не устраивает - рекомендую заняться изучением языка Java... Там эта проблема решена.
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
DaSharm
Гость
« Ответ #2 : 23-01-2005 18:04 » 

Ну...тогда я просто не понимаю: как узнать рамер массива char? Типа, сколько букв в строке (ох нет, strlen не катит!А Sizeof выдает ваще какую-то пургу). Ещё мне нужно обрезать этот массив (уменьшать) без потери содержимого и увеличивать без потери содержимого (например, на 5 букв). Как мне это делать??? Просто не понимаю и все...
Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #3 : 23-01-2005 18:21 » 

DaSharm, все достаточно просто, надо явно следить за выделением и использованием памяти. Никто в с++ за програмера это делать не будет. если не хочешь с этими вещами париться напросто пользуйся готовыми классами std::string , ATL::CString.
« Последнее редактирование: 23-01-2005 18:24 от Pu » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Pu
Большой босс

ru
Offline Offline
78


« Ответ #4 : 23-01-2005 18:44 » 

и еще библиотека  stl доступна в кодах, но уверен что тебе это скоро надоест, почитай литературу имей представление и пользуйся библиотеками. Это гораздо эффективнее.
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
DaSharm
Гость
« Ответ #5 : 23-01-2005 20:06 » 

Ну...тогда обясните мне пожалуйста, что здесь не так:


          char wsData;
   int TheByte[1];
   int reBytes;

   reBytes=recv(DaSocket,&wsData,1,NULL);
   if(reBytes>0){
       TheByte[0]=wsData[0];
      DataArrival(&wsData,reBytes);
   }

      И я получаю ошибку, мол, невозможно достать элемент 0 массива wsData. Блин, так как же достать первый символ из wsData? (мне нужен именно первый символ, без 0x00). И ещё, почему компилятор добавит ещё одну ошибку, когда я обявлю не  int TheByte[1]; а int TheByte[0]; Не понял
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #6 : 23-01-2005 20:24 » 

DaSharm, посмотри как ты объявил wsData. Просто как символ. Впоследствии ты пытаешся его использовать как массив. Вот и компилятор и ругается На несоответсвие типов.
В С и С++ Когда объявляется массив, в скобках указывается количество элементов данного массива. Массив также может быть переменной длины. Тогда просто проставляются две квадратные скобки без указания числа. Впоследствии может быть выделена память под данный массив. Массив не может быть определен с нулевой длиной. Он просто не будет иметь смысла. Индекс массива начинается с нуля. Порядок счета по одному элементу. Индекс массива положительный или нуль.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
DaSharm
Гость
« Ответ #7 : 23-01-2005 20:31 » 

Спасибо. Это понял. Но тогда как мне достать первый символ?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #8 : 23-01-2005 20:37 » 

Тип char это один байт. Напрямую с ним и работай. Убери скобки массива и вперед. Просто тебе предется приводить типы. Так как TheByte У тебя объявлен как int. Запись примерно такая TheByte[0]=(int) wsData;
« Последнее редактирование: 23-01-2005 20:40 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #9 : 23-01-2005 21:12 » 

Вообще то
Цитата
Понял суть работы с указателями.
подразумевает что такие глупые вопросы были поняты Улыбаюсь и задаваться не будут.

Итак.
1.
Память при надписи
int a; 
Выделяется автоматически в 32 разрядных системах - это 4 байта целое знаковое число, где знаком является самый старший (левый) бит значения числа...

При обращении &a значением выражения будет адрес (4 байтное целое беззнаковое число) которое покажет место в виртуальной памяти виндовс где именно лежит само значение числа а.

Однако &a это НЕ указатель как таковой, а reference - ссылка типа указателя. В данном случае мы имеем возможность не следить за размерностью типа данных....

int a[10] это массив значений каждое из которых целое знаковое 4-х байтное число - см. предыдущий пример...

При обращении &a мы имеем адрессную ссылку на место ПЕРВОГО элемента в массиве в С++ за номером 0.

При работе с прямым указателем мы не пишем a[10]
Мы работаем с
int * a;
Однако при такой записи памяти нам не выделено и мы должны использовать явное выделение ....
a = malloc(sizeof(int)*10)
либо
a = new int[10];
Только после этого мы имеем возможность что-то писать в УКАЗАТЕЛЬ - который указывает на РЕАЛЬНУЮ память.

После того как память стала не нужна необходимо использовать free или delete

Трети вариант использования указателя...

int a[10];
int * b;

b = &a;

В данном случае мы получим указатель b который указывает на ту же область что и a но работать с ним нам будет нужно так.
b+1 ==
Записан

А птичку нашу прошу не обижать!!!
Pu
Большой босс

ru
Offline Offline
78


« Ответ #10 : 24-01-2005 06:28 » 

Гром, всегда считал, что при объявлении массива char a[100]; как выше привел ты

char a[100];
char * ab;

ab = &a;

упоминание "a" дает нам ссылку на первый элемент массива, те я бы изобразил так -

char a[100];
char *ab = а;

что эквивалентно

ab = &a[0];

а при записи такой штуки, как 

ab = &a;

компилятор дает ошибочку. Жаль - Types pointed to are unrelated;

ну и еще поправочка -

b+1 == 1];
Гром, может ты не выспался после выходных?  Быть такого не может  Ага
« Последнее редактирование: 24-01-2005 06:34 от Pu » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
xelos
Гость
« Ответ #11 : 24-01-2005 08:50 » new

насчет длины строк, если строки сформированы согласно ANSI, то они заканчиваются нулевым символом, что и позволяет определить длину строки. Однако, это не означает, что можно определить длину массива char, если он создан не как строка.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #12 : 24-01-2005 09:44 » 

Pu
ab = a; вполне работает.

& не нужен тут ты прав.

А в остальном ты прав - поздно было уже - спать хотелось... Жаль
Записан

А птичку нашу прошу не обижать!!!
Pu
Большой босс

ru
Offline Offline
78


« Ответ #13 : 24-01-2005 10:56 » 

Гром, "Моя твоя понимает" Ага .
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
DaSharm
Гость
« Ответ #14 : 24-01-2005 20:19 » 

ОК. ПОнял... Теперь, ещё вопросик:

Допустим, у меня есть байтовый массив

BYTE a[];

Вопросы:
как мне
 1. Увеличивать размер массива без потери данных в нем
 2. Уменьшать размер массива без потери данных в нем

Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #15 : 24-01-2005 20:54 » 


DaSharm ,

BYTE a[N];
это статический массив, его размер не поменяешь. ;)

создавай динамический:
BYTE *a;
a=new BYTE[N];

-------------------------------------
1. Увеличивать размер массива без потери данных в нем (то есть неинициализированна только новая часть увеличенного массива)

увеличить размер массива - пусть N2>N . Создаём новый массив
BYTE *anew=new[N2];

//копируем старый в новый
for(DWORD i=0;i<N;i++) anew[i]=a[i];

//удаляем старый массив
delete [] a;

//настраиваем указатель на новый массив
a=anew;

-------------------------------------
2. Уменьшать размер массива без потери данных в нем - такое невозможно ;) можно сохранить только то, что влезет в новый, уменьшенный массив

уменьшить размер массива - пусть N2<N . Создаём новый массив
BYTE *anew=new[N2];

//копируем что можно
for(DWORD i=0;i<N2;i++) anew[i]=a[i];

//удаляем старый массив
delete [] a;

//настраиваем указатель на новый массив
a=anew;
« Последнее редактирование: 14-04-2006 21:34 от Алексей1153 » Записан

Pu
Большой босс

ru
Offline Offline
78


« Ответ #16 : 25-01-2005 06:23 » 

DaSharm, либо используй динамические массивы из STL.
Код:
<vector>
......
std::vector<BYTE> vector_byte;
for( BYTE b = 0; b<30; b++)
  vector_byte.push_back(b); // добавление элементов в конец
BYTE b1 = vector_byte[10]; // извлечение по индексу
vector_byte.pop_back(); // удаление из конца
int size = vector_byte.size(); //получение размера массива
vector_byte.clear();
......
ну и тд в том же духе, возможностей хоть отбавляй Улыбаюсь
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
PooH
Глобальный модератор

ru
Offline Offline
Пол: Мужской
... и можно без хлеба!


« Ответ #17 : 01-03-2005 14:16 » 

Pu
ab = a; вполне работает.

& не нужен тут ты прав.

А в остальном ты прав - поздно было уже - спать хотелось... Жаль

кстати, если написать ab=a - происходит неявное преобразование типов.
ab=(char*)&a - у меня тоже обычно работает.
Записан

Удачного всем кодинга! -=x[PooH]x=-
PooH
Глобальный модератор

ru
Offline Offline
Пол: Мужской
... и можно без хлеба!


« Ответ #18 : 01-03-2005 14:43 » 

кстати (еще раз), с указателями проще разобраться, если четко для себя понять две вещи (тривиальные, не совсем соответствующие действительности, но так  проще понять указатели):

1. Указатель - это просто адрес ячейки памяти - число. (можно провести аналогию с почтовым адресом)
2. Каждый указатель знает (есть у него такое свойство) какой тип данных находится по этому адресу (по аналогии - школа, дом, библиотека).

Приведу пример (на аналогиях):

БИБЛИОТЕКА var1; //собстветно само здание библиотеки
БИБЛИОТЕКА* ptr1; // почтовый адрес библиотеки (именно БИБЛИОТЕКИ)

ДОМ* ptr2; //почтовый адрес какого-либо дома (не обязательно библиотеки, школа тоже дом)

мы имеем полное право записать
prt2=ptr1; // т.е. адреса ДОМ-а указывает на библиотеку

правда компилятор может от нас потребовать написать:
prt2=(ДОМ*)ptr1; //т.е. указать, что на самом деле почтовый адрес библиотеки является почтовым адресом дома.

-----------------
допустим у нас есть две библиотеки: научная - bib1 и художественная - bib2:
БИБЛИОТЕКА bib1,bib2;
БИБЛИОТЕКА *pbib1, *pbib2; // почтовые адреса каких-то библиотек

запись &bib1 нам возвращает почтовый адрес научной библиотеки (с этим многие могут поспорить, но так проще разобраться с указателями)
запись &bib2 нам возвращает,соответственно,почтовый адрес художественной библиотеки

pbib1=&bib1;
pbib2=&bib2;

мы хотим пойти в художественную, запись pbib2 содержит почтовый адрес, указывая *pbib2 - мы попадает в саму библиотеку.

во собственно и все... и указатели к массивам никакого (прямого) отношения не имеют (на сколько я знаю)
-----------------------

P.S.: пример придумывал находу... так что если чё - извиняйте...
Записан

Удачного всем кодинга! -=x[PooH]x=-
PooH
Глобальный модератор

ru
Offline Offline
Пол: Мужской
... и можно без хлеба!


« Ответ #19 : 01-03-2005 14:49 » 

ксати (третий раз), если ты создал "почтовый адрес" - это совсем не значит, что ты построил библиотеку и даже не значит, что там есть место (типа бульдозером все разровняли) где ее строить. И если сразу начать завозить по этому адресу книги очень вероятно, что их привезут не в библиотеку (которая еще не построена), а к кому-нибудь домой или в какой-нибудь магазин, который находится на месте (по адресу) "запланированной" библиотеки.
« Последнее редактирование: 01-03-2005 14:54 от PooH » Записан

Удачного всем кодинга! -=x[PooH]x=-
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 02-03-2005 07:54 » 

PooH,

интересный пример. +1
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #21 : 02-03-2005 15:33 » 

И еще - потрясающий правильный пример!!!
Записан

А птичку нашу прошу не обижать!!!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines