it-place.net > Уроци > C-Cplusplus
Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 Основи на указатели в C
  1. Основи на указатели в C
     
Автор  das_efx (11.03.2005 23:49)  съобщение до автора
Погледнат  7435 пъти  добави към любими
Оценка  добави коментар
Гласове  7  изпрати на приятел
Коментари  (4)  абонирай се за C-Cplusplus
    Страница 1 / 1

 



Накратко указтелят е променлива, която сочи адреса на даден обект в паметта.

Указателят се декларира по следният начин:

CODE
1
[i]тип[/i] *име;

Tип може да бъде всеки валиден C тип. След него се поставя знака "*", следван от името на указателя.

Типът на указателя е много важен. Винаги, когато декларирате указател, трябва да го декларирате от типът на променливата, която той ще "сочи". По напред в урока ще разберете защо това е важно.

Има два важни оператора свързани с указателите. Операторът & и операторът *. Операторът & връща адреса на променливата стояща след него. Операторът * връща стойноста съдържаща се на адреса, който указателят сочи.

CODE
1
2
3
4
int *p, i = 10;

p = &i;
printf("%d", *p);

Нека да разгледаме кода по-подрбоно. На първия ред се декларира указател от цяло число и променлива цяло число, която се инициализира със стойност 10. След това на указателят p се присвоява адреса на i. Или по друг начин казано p сочи i. Това се нарича индиректност. На третият ред се отпечатва стойноста на i посредством оператора "*" следван от името на указателя.

Също така можете да присвоявате стойност на променливата сочена от указателя.

CODE
1
2
3
4
5
6
int *p, i;

p = &i;
*p = 10;

printf("%d", i);

Когато операторът "*" бъде приложен в лявата част на конструкцията за присвояване се присвоява стойност на променливата сочена от указателя индиректно.

Сега да видим защо типът на указателят е толкова важен. Да кажем, че имаме един указател от тип int и една променлива i от тип int.

CODE
1
2
p = &i;
*p = 10;

При това индиректно присвояване компилатор знае, че трябва да копира 4 байта в i(при 4 байтов int). Но какво ще стане примерно, ако указателят е декларарин с тип double и се опитаме да присвоим double стойност на i? Компилаторът знае, че трябва да копира 8 байта(при 8 байтов double), но i е 4 байта. Той ще копира 4 байта в задалената памет за i, но другите 4 байта ще се изгубят. Това ще предизвика грешка. Затова винаги когато декларирате указател го декларирайте от типа на променливата/те, които ще сочи.

Неможете да използвате указател преди той да съдържа адреса на някой обект в паметта.

Освен двата оператора & и * има още четири аритметични опеатора, които могат да се използват с указателите. Те са ++ -- - +. Не можете да прибавяте дробна стойност на указател или да изваждате. Можете да прибавяте и изваждате само целочислени стойности. Указателна аритметика не е като обикновенната. Тя се извършва в зависимост от типа на указателя.

Да кажем, че p е указател от тип int(4 байтов) и съдържа адрес 100 в паметта. Като се приложи оператора за инкрементиране ++.

CODE
1
p++

p вече ще съдържа адрес 104.

CODE
1
p += 100

Сега p ще съдържа адрес 204.

Неможете да прилагате никакви други аритметични операции освен събиране и изваждане.

Указатели и масиви

Масив без индекс всъщност е указател към началото на масива.

Примерно:

CODE
1
2
3
4
5
char str[10] = "123456789";
char *p;

p = str; /* Взимане адреса на началото на str */
printf("%c %c", *p, *(p+1)); /* Това ще отпечата 1 и 2 */

Така много лесно можете да достигнете до всеки един елемент от масива.
Защо се получава така? Ами понеже масив без индекс всъщност е указател към началото на масива... *p отпечатва 1, *(p+1) отпечатва 2 защото към p прибавяме 1 т.е p вече сочи към следващият елемент. Ако началото на масива се намира на адрес 100 то следващият елемент ще се намира на адрес 101, следващият на 102 и т.н.

Можете да създавате и масиви от указатели. Това става по същият начин както при всички типове променливи. Този код създава масив от указатели от тип char с 5 елемента.

CODE
1
char *p[5];

Така записвате адреса на i в 2 елемент.

CODE
1
p[1] = &i;

Така можете да присвоите стоност на i.

CODE
1
*p[1] = 10;

Указатели и низови константи

Когато компилаторът срещне низ той го съхранява в низова таблица на програмата и създава указател към него. Така можете да декларирате указател сочещ низова константа.

CODE
1
char *p = "some text";

Компилаторът връша адреса на низа "some text" в низовата таблица на указателя.

Така лесно можете да отпечатате низа сочен от указателя посредством някой функция за изход. Примерно puts(). Нейният аргумент е char указател.

CODE
1
puts(p); /* Отпечатва "some text" */

Тка можете да създадете низова таблица с указател.

CODE
1
2
3
4
char *p[] {
 
"niz", "niz1", "niz2" } ;

puts(p[1]); /* Отпечатва "niz1" */



   


Ключови думи: c C++ указател адрес памет оператор компилатор


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

qko!!!!!!!!!
nqmam dumi kratko i qsno.

  amd_dogi на 12.08.2008 21:51

При повторен прочит усетих, че ти говориш за случая:
 CODE
1
2
3
int i;
double *p = &i;
*p = 2.5;
Забележката ми е вярна, но излишна в случая, защото ти явно говориш за присвояване на сочената от указателя стойност именно при дереференциране чрез оператор *. Първоначално реших, че говориш за самото присвояване на адрес.

  Izida на 13.09.2006 00:02

Но какво ще стане примерно, ако указателят е декларарин с тип double и се опитаме да присвоим double стойност на i? Компилаторът знае, че трябва да копира 8 байта(при 8 байтов double), но i е 4 байта. Той ще копира 4 байта в задалената памет за i, но другите 4 байта ще се изгубят.
Kакто ти сам казваш, указателят не съдържа стойността на обекта i, а неговия адрес. А адресите на променливи са с еднакъв размер независимо от типа им. Пример: на адрес 100 може да има int, double, структура или каквото друго решиш. Така че в този момент няма значение какъв е типа на указателя - указател от какъвто и да е тип може да побере адрес на всякаква променлива в себе си. Иначе нямаше да има указатели от тип void.

Типът на указателя има значение при ползване на оператор * - тогава вече компилаторът трябва да знае каква стойност се сочи от съдържания в указателя адрес, за да знае какво да прави с нея. И понеже С позволява да се застреляш в крака, можеш да промениш с cast типа на сочения от указателя обект преди да ползваш оператор *.

  Izida на 12.09.2006 11:41

Можем ли да смятаме, че указателите в С могат да се използват така както са описани и в С++?

  paro777 на 21.04.2006 17:52

 

 
  • Интересно от Софтуер
 



IT-PLACE.NET © 2004 - 2008