Вирази вказівника: * ptr ++, * ++ ptr та ++ * ptr


128

Нещодавно я стикався з цією проблемою, яку я не в змозі зрозуміти сам.

Що дійсно означають ці три вирази ?

*ptr++
*++ptr
++*ptr

Я спробував Річі. Але, на жаль, не зміг слідкувати за тим, що він розповів про ці 3 операції.

Я знаю, що всі вони виконуються для збільшення покажчика / значення, на яке вказували. Я також можу здогадатися, що може бути багато речей щодо пріоритетності та порядку оцінки. Як і один приріст, вказівник спочатку виймає вміст цього вказівника, один просто виймає вміст, а потім збільшує вказівник тощо. Як ви бачите, у мене немає чіткого розуміння їхніх фактичних операцій, що я хотів би зробити зрозуміти якомога швидше. Але я справді втрачаю, коли отримую можливість застосувати їх у програмах. Наприклад:

int main()
{
    const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

дає мені такий вихід:

ello

Але я сподівався, що це буде надруковано Hello. Один остаточний запит. Надайте, будь ласка, приклади того, як кожен вираз працює у заданому фрагменті коду. Оскільки більшу частину часу над моєю головою пролітає лише простий абзац теорії.


6
Ви пропустили четверте: (*ptr)++(дужки, необхідні для *ptr++
відключення

15
Тому що ви наростили вказівник перед тим, як надрукувати його. Ви хотіли, щоб (* p) та printf ("% c", * p ++);
dcaswell

Відмінні запитання для співбесіди. Обмежене практичне використання. Я б хотів, щоб у C не було цих покажчиків :)
Himanshu

5
@Himanshu Якщо це пече локшину вашого співбесідника, спробуйте це: майте глобальний вказівник char* p, вказуючи на дійсну закінчену рядок унікальних символів. Тоді є функція , fn(char ch)яка друкує якch параметр і поточний символ , на який вказує p. Тепер попросіть fn(*p++);Q: Чи fnдрукує один і той же символ двічі ? Ви були б вражені, скільки професорів помилково розуміють це питання.
WhozCraig

1
оскільки p вказує на рядковий const char* p = "Hello";
буквал, який

Відповіді:


275

Ось детальне пояснення, яке, я сподіваюся, буде корисним. Почнемо з вашої програми, оскільки це найпростіше пояснити.

int main()
{
    const char *p = "Hello";
    while(*p++)
        printf("%c",*p);
    return 0;
}

Перше твердження:

const char* p = "Hello";

оголошує pяк покажчик на char. Коли ми говоримо "вказівник на char", що це означає? Це означає, що значення p- це адреса а char;pповідомляє нам, де в пам’яті є якийсь простір для відведення char.

Оператор також ініціалізується, pщоб вказати на перший символ у рядковому літералі "Hello". Заради цієї вправи, важливо зрозуміти , pяк вказує не на весь рядок, але тільки на перший символ, 'H'. Зрештою, pце вказівник на один char, а не на весь рядок. Значення p- адреса 'H'в"Hello" .

Потім ви встановлюєте цикл:

while (*p++)

Що означає умова циклу *p++? Тут працюють три речі, які викликають спантеличення (принаймні, поки не з'явиться знайомство):

  1. Пріоритет двох операторів, постфікс ++ та непрямий*
  2. Значення вираження приросту постфікса
  3. Побічний ефект вираження приросту постфікса

1. Прецедент . Швидкий погляд на таблицю пріоритетності для операторів скаже вам, що приріст постфікса має більший пріоритет (16), ніж дереференція / непрямість (15). Це означає , що комплексне вираз *p++збирається бути згруповані наступним чином: *(p++). Тобто *частина буде застосована до значення p++частини. Тож давайте візьмемо p++участь спочатку.

2. Значення виразу постфіксу . Значення p++- це значення p до приросту . Якщо у вас є:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

вихід буде:

7
8

тому що i++оцінюється до iприросту. Аналогічно p++збирається оцінити до поточного значення p. Як ми знаємо, поточне значення p- це адреса 'H'.

Отже, тепер p++частина *p++була оцінена; це поточне значення p. Тоді *частина трапляється. *(current value of p)означає: отримати доступ до значення за адресою, яку має p. Ми знаємо, що значення за цією адресою є 'H'. Отже вираз *p++оцінюється на'H' .

А тепер зачекай хвилину, ти кажеш. Якщо *p++оцінюється 'H', чому це не 'H'друкується у наведеному вище коді? Ось де побічні ефекти з’являються .

3. Постфікс-експресія побічні ефекти . Постфікс ++має значення поточного операнда, але він має побічний ефект збільшення цього операнда. Так? Погляньте на цей intкод ще раз:

int i = 7;
printf ("%d\n", i++);
printf ("%d\n", i);

Як зазначалося раніше, вихід буде:

7
8

Коли i++оцінюється в першому printf(), він оцінює до 7. Але стандартні гарантії C , що в якийсь - то момент перед другим printf()починає виконання команд, побічний ефект від ++оператора буде мати місце. Тобто, перш ніж відбудеться друге printf(), iбуде збільшено в результаті ++оператора в першому printf(). Це, до речі, одна з небагатьох гарантій, які стандарт дає про терміни побічних ефектів.

У вашому коді тоді, коли вираження *p++оцінюється, воно оцінюється до 'H'. Але до моменту, коли ви досягнете цього:

printf ("%c", *p)

той побічний побічний ефект відбувся. pбуло збільшено. Ого! Це вже не вказує на 'H'минуле одного персонажа 'H': на 'e', іншими словами. Це пояснює ваш результат, котрий працює на коктейлі:

ello

Звідси хор корисних (і точних) пропозицій в інших відповідях: щоб надрукувати Отриману вимову, "Hello"а не її колегу-кокні, вам потрібно щось на зразок

while (*p)
    printf ("%c", *p++);

Стільки за це. Що з рештою? Ви запитаєте про значення цих:

*ptr++
*++ptr
++*ptr

Ми тільки що говорили про перший, так що давайте подивимося на другий: *++ptr.

У попередньому поясненні ми бачили, що приріст постфікса p++має певний пріоритет , значення та побічний ефект . Приріст префікса ++pмає той самий побічний ефект, що і його аналог постфікса: він збільшує свій операнд на 1. Однак він має інший пріоритет і інше значення .

Приріст префікса має нижчий пріоритет, ніж постфікс; він має пріоритет 15. Іншими словами, він має той же пріоритет, що й оператор перенаправлення / опосередкування *. У виразі, як

*++ptr

Що важливо, це не пріоритет: два оператори однакові за пріоритетом. Отже, асоціативність починається. Приріст префікса та оператор непрямості мають асоціативність справа-наліво. З - за цього асоціативність, операнд ptrбуде групуватися з крайнім правим оператором ++перед оператором лівіше, *. Іншими словами, вираз збирається групуватися *(++ptr). Отже, як і з *ptr++іншої причини, і тут *частина буде застосована до значення++ptr частини.

То яка ж цінність? Значення вираження приросту префікса - це значення операнду після приросту . Це робить його зовсім іншим звіром від оператора приросту постфікса. Скажімо, у вас є:

int i = 7;
printf ("%d\n", ++i);
printf ("%d\n", i);

Вихід буде:

8
8

... відрізняється від того, що ми бачили з оператором postfix. Аналогічно, якщо у вас є:

const char* p = "Hello";
printf ("%c ", *p);    // note space in format string
printf ("%c ", *++p);  // value of ++p is p after the increment
printf ("%c ", *p++);  // value of p++ is p before the increment
printf ("%c ", *p);    // value of p has been incremented as a side effect of p++

вихід буде:

H e e l                // good dog

Ви бачите, чому?

Тепер ми переходимо до третього висловом ви запитали про, ++*ptr. Це насправді найвибагливіший. Обидва оператори мають однаковий пріоритет і право-ліву асоціативність. Це означає, що вираз буде групуватися ++(*ptr). ++Частина буде застосовуватися до значення *ptrчастини.

Отже, якщо ми маємо:

char q[] = "Hello";
char* p = q;
printf ("%c", ++*p);

напрочуд егоїстичний результат буде:

I

Що?! Гаразд, тому *pчастина буде оцінюватися 'H'. Тоді ++вступає в гру, і в цей момент він буде застосований до 'H', а не до вказівника! Що станеться, коли ви додасте 1 до 'H'? Ви отримуєте 1 плюс значення ASCII 'H', 72; ви отримуєте 73. Представляйте це як char, і ви отримуєтеchar зі значенням ASCII 73: 'I'.

Це стосується трьох виразів, про які ви запитали у своєму запитанні. Ось ще один, згаданий у першому коментарі до вашого питання:

(*ptr)++ 

Цей теж цікавий. Якщо у вас є:

char q[] = "Hello";
char* p = q;
printf ("%c", (*p)++);
printf ("%c\n", *p);

це дасть вам цей захоплений результат:

HI

Що відбувається? Знову ж таки, це питання пріоритетності , значення вираження та побічних ефектів . Через дужки *pчастина трактується як первинний вираз. Первинні вирази козирують на все інше; їх оцінюють першими. І *p, як відомо, оцінює 'H'. Решта виразу, ++частина, застосовується до цього значення. Отже, у цьому випадку(*p)++ стає 'H'++.

Яка цінність 'H'++? Якщо ви сказали 'I', ви забули (вже!) Наше обговорення значення та побічного ефекту із збільшенням постфікса. Запам'ятайте, 'H'++оцінює до поточного значення 'H' . Тож спочатку printf()збирається надрукувати 'H'. Потім, як побічний ефект , до 'H'якого збираються наростити 'I'. Друга printf()друкує це 'I'. І у вас є ваше веселе привітання.

Гаразд, але в цих останніх двох випадках навіщо мені це потрібно

char q[] = "Hello";
char* p = q;

Чому я просто не можу мати щось подібне

/*const*/ char* p = "Hello";
printf ("%c", ++*p);   // attempting to change string literal!

Тому що "Hello"це рядковий літерал. Якщо ви намагаєтеся ++*p, ви намагаєтеся змінити 'H'рядок на 'I', роблячи всю рядок "Iello". У C рядкові літерали є лише для читання; спроба модифікувати їх викликає невизначене поведінку."Iello"в англійській мові також не визначено, але це просто збіг.

І навпаки, не можна цього мати

char p[] = "Hello";
printf ("%c", *++p);  // attempting to modify value of array identifier!

Чому ні? Тому що в цьому випадку pє масив. Масив - це не змінне l-значення; ви не можете змінити, де pточки за попереднім або після збільшення чи зменшення, оскільки ім'я масиву працює так, ніби це постійний покажчик. (Це насправді не так; це просто зручний спосіб поглянути на це.)

Підводячи підсумок, ось три речі, про які ви запитали:

*ptr++   // effectively dereferences the pointer, then increments the pointer
*++ptr   // effectively increments the pointer, then dereferences the pointer
++*ptr   // effectively dereferences the pointer, then increments dereferenced value

І ось четверте, кожне трохи так весело, як і інші три:

(*ptr)++ // effectively forces a dereference, then increments dereferenced value

Перший і другий завершаться, якщо ptrце дійсно ідентифікатор масиву. Третій та четвертий завершаться, якщо ptrвказуватимуть на літеральний рядок.

Там у вас є. Я сподіваюся, що зараз усе кристально. Ви були чудовою аудиторією, і я буду тут весь тиждень.


22
Перш ніж зайти на цей форум, я шукав 3 "С" книги, якими я володію. Я також спробував кілька помітних навчальних посібників в Інтернеті. Але жодне з них не наближається до вашого пояснення (особливо так, як ви все це склали). Ви не лише відповіли на запитання, яке я поставив, але і ви обговорили набагато більше речей з низового рівня. Насправді ви сьогодні навчили мене багато основного, чого мені бракувало раніше. Я не міг не змінити прийняту відповідь. :) Знову дякую.
виділено

26
+1 Я думаю, що це найкраща довга відповідь, яку я прочитав у програмі SO. Я думаю, кожен міг багато чого навчитися з цієї відповіді.
Шафік Ягмур

9
Ви, сер, повинні написати книгу про C.
Діллон Бертон

1
Яка гарна відповідь на гарне запитання! Молодці @verbose!
benka

7
@verbose вам , сер, жив до вашого імені .. :)
sleeping_dragon

44

Припустимо, ptrвказує на i-й елемент масиву arr.

  1. *ptr++оцінює до arr[i]та встановлює, ptrщоб вказувати на (i + 1) -й елемент arr. Це еквівалентно *(ptr++).

  2. *++ptrвстановлює, ptrщоб вказувати на (i + 1) -й елемент arrі оцінює на arr[i+1]. Це еквівалентно *(++ptr).

  3. ++*ptrзбільшується arr[i]на одиницю і оцінюється до її підвищеного значення; вказівник ptrзалишається недоторканим. Це еквівалентно ++(*ptr).

Є ще один, але вам потрібні дужки, щоб написати його:

  1. (*ptr)++збільшується arr[i]на одиницю і оцінюється до її значення, перш ніж збільшуватися; вказівник ptrзнову залишається недоторканим.

Решту ви можете самі придумати; на це також відповів @Jaguar.


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Прочитайте тут про операторів до збільшення та післязростання


Це дасть Helloвихід

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Increment the pointer here 
    return 0;
}

@ Nik-Lz Так, вихід будеHello
Jainendra

7

Стан у вашому циклі поганий:

while(*p++)
    printf("%c",*p);

Це те саме, що

while(*p)
{
    p++;
    printf("%c",*p);
}

І це неправильно, це має бути:

while(*p)
{
    printf("%c",*p);
    p++;
} 

*ptr++те саме *(ptr++), що є:

const char  *ptr = "example";
char  value;

value = *ptr;
++ptr;
printf("%c", value); // will print 'e'

*++ptrте саме *(++ptr), що є:

const char  *ptr = "example";
char  value;

++ptr;
value = *ptr;
printf("%c", value); // will print 'x'

++*ptrте саме ++(*ptr), що є:

const char  *ptr = "example";
char  value;

value = *ptr;
++value;
printf("%c", value); // will print 'f' ('e' + 1)

Я повністю погоджуюся з першою частиною відповіді. У другій частині ініціалізація покажчиків (на цілі числа!) Цілими числами заплутає те, хто намагається зрозуміти використання вказівника.
nickie

4

Ви маєте право на пріоритет, зауважте, що *має перевагу над збільшенням префікса, але не над збільшенням префікса. Ось як ці розбивки:

*ptr++ - перехід зліва направо, відмежування вказівника, а потім збільшення значення вказівника (не те, на що воно вказує, через перевагу постфікса над дереференцією)

*++ptr - збільшуючи вказівник, а потім перенапрягаючи його, це тому, що префікс і дереференція мають однаковий пріоритет, і тому вони оцінюються в порядку справа наліво

++*ptr- аналогічно вищевикладеному з точки зору пріоритетності, знову рухаючись праворуч ліворуч з метою дереференції вказівника, а потім збільшення на те, на що вказує вказівник. Зауважте, що у вашому випадку ця ситуація призведе до невизначеної поведінки, оскільки ви намагаєтесь змінити змінну, доступну лише для читання ( char* p = "Hello";).


3

Я збираюся додати свою думку, тому що в той час як інші відповіді правильні, я думаю, що у них щось не вистачає.

 v = *ptr++

засоби

 temp = ptr;
 ptr  = ptr + 1
 v    = *temp;

Де як

 v = *++ptr

засоби

 ptr = ptr + 1
 v   = *ptr

Важливо розуміти, що збільшення посту (і після декременту) означає

 temp = ptr       // Temp created here!!!
 ptr  = ptr + 1   // or - 1 if decrement)
 v    = *temp     // Temp destroyed here!!!

Чому це важливо? Ну а в С це не так важливо. У C ++, хоча це ptrможе бути складний тип, як ітератор. Наприклад

 for (std::set<int>::iterator it = someSet.begin(); it != someSet.end(); it++)

У цьому випадку, оскільки itце складний тип, it++можливо, це має побічні ефекти через tempстворення. Звичайно, якщо вам пощастить, компілятор спробує викинути код, який не потрібен, але якщо конструктор іструктора ітератора зробить що-небудь, тоді it++він покаже ці ефекти, коли він створює temp.

Коротке, що я намагаюся сказати, - це написати те, що ти маєш на увазі . Якщо ви маєте на увазі збільшення ptr, тоді ++ptrне пишіть ptr++. Якщо ви маєте на увазі, temp = ptr, ptr += 1, tempтоді пишітьptr++


0
*ptr++    // 1

Це те саме, що:

    tmp = *ptr;
    ptr++;

Отже, значення об'єкта, на який вказують, ptrотримується, потім ptrзбільшується.

*++ptr    // 2

Це те саме, що:

    ++ptr;
    tmp = *ptr;

Отже, покажчик ptrзбільшується, потім ptrчитається об'єкт, на який вказують .

++*ptr    // 3

Це те саме, що:

    ++(*ptr);

Так об'єкт, на який вказують, ptrзбільшується; ptrсама по собі незмінна.


0

постфікс та префікс мають вищий пріоритет, ніж дереференція

* ptr ++ тут ​​розміщують приріст ptr, а потім вказують на нове значення ptr

* ++ ptr тут Pre Increment fist, потім вказує на нове значення ptr

++ * ptr тут спочатку отримують значення ptr, що вказує на та збільшує, що vlaue


1
Це неправильно. Постфікс має більшу перевагу, але префікс має такий самий пріоритет, як і відновлення.
багатослівний

0

Вирази вказівника: * ptr ++, * ++ ptr та ++ * ptr:

Примітка : покажчики повинні ініціалізуватися та мати дійсну адресу. Тому що в оперативній пам’яті, крім нашої програми (a.out), є набагато більше одночасно запущених програм, тобто якщо ви намагаєтеся отримати доступ до деякої пам’яті, яка не була зарезервована для вас, ОС стане через помилку сегментації.

Перш ніж пояснити це, давайте розглянемо простий приклад?

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;//uninitialized pointer.. must be initialized
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr = *ptr + 1;//*ptr means value/data on the address.. so here value gets incremented
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        /** observe here that "num" got changed but manually we didn't change, it got modified by pointer **/
        ptr = ptr + 1;//ptr means address.. so here address got incremented
        /**     char pointer gets incremented by 1 bytes
          Integer pointer gets incremented by 4 bytes
         **/
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

проаналізуйте вихід вищевказаного коду, я сподіваюся, що ви отримали вихід з вищевказаного коду. Зверху вище зрозуміло одне, що ім'я вказівника ( ptr ) означає, що ми говоримо про адресу, а * ptr означає, що ми говоримо про значення / дані.

СЛУЧАЙ 1 : * ptr ++, * ++ ptr, * (ptr ++) та * (++ ptr):

Вище згадані всі 4 синтаксису схожі, у всіх, address gets incrementedокрім того, як адреса збільшується, це різне.

Примітка : для вирішення будь-якого виразу з’ясуйте, скільки операторів є в виразі, а потім з’ясуйте пріоритети оператора. I кілька операторів, що мають однаковий пріоритет, перевіряють порядок еволюції або асоціативності, який може праворуч (R) вліво (L) від ліворуч направо.

* ptr ++ : Тут знаходяться 2 оператори, а саме: дереференція (*) та ++ (приріст). Обидва мають однаковий пріоритет, а потім перевіряють асоціативність, яка є R до L. Тож починає вирішувати справа наліво, незалежно від того, які оператори виходять першими.

* ptr ++ : перший ++ з'явився під час вирішення від R до L, тому адреса збільшується, але збільшується її пост.

* ++ ptr : Те саме, що і перша, тут також адреса збільшується, але її попереднє збільшення.

* (ptr ++) : Тут є 3 оператори, серед яких групування (), що мають найвищий пріоритет, тому перший ptr ++ вирішений, тобто адреса збільшується, але розміщується.

* (++ ptr) : Те саме, що описано вище, і тут адреса збільшується, але попередньо збільшується.

СЛУЧАЙ 2 : ++ * ptr, ++ (* ptr), (* ptr) ++:

вище згадані всі 4 синтаксису схожі, у всіх значення / дані збільшуються, але як змінюється значення, це різне.

++ * ptr : перший * прийшов під час вирішення з R на L, тому значення змінюється, але його попереднє збільшення.

++ (* ptr) : те саме, що і вище, значення змінюється.

(* ptr) ++ : Тут є 3 оператори, серед яких групування (), що має найвищий пріоритет, Inside () * ptr є, тому спочатку * ptr вирішено, тобто значення збільшується, але розміщується.

Примітка : ++ * ptr і * ptr = * ptr + 1 обидва однакові, і в обох випадках значення змінюється. ++ * ptr: використовується лише 1 інструкція (INC), безпосередньо значення змінюється за один кадр. * ptr = * ptr + 1: тут перше значення збільшується (INC), а потім присвоюється (MOV).

Щоб зрозуміти все вище, різний синтаксис приросту вказівника дозволяє розглянути простий код:

#include<stdio.h>
int main()
{
        int num = 300;
        int *ptr;
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//address changed(post increment), value remains un-changed
//      *++ptr;//address changed(post increment), value remains un-changed
//      *(ptr)++;//address changed(post increment), value remains un-changed
//      *(++ptr);//address changed(post increment), value remains un-changed

//      ++*ptr;//value changed(pre increment), address remains un-changed
//      (*ptr)++;//value changed(pre increment), address remains un-changed
//      ++(*ptr);//value changed(post increment), address remains un-changed

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

У наведеному вище коді спробуйте коментувати / скасовувати коментарі та аналізувати результати.

Покажчики як постійні : немає способів, за допомогою яких можна зробити покажчики постійними, я мало тут згадую.

1) Const INT * р OR ІНТ сопз * р : Тут valueє константа , адреса не постійний тобто де р вказує? Якась адреса? Що за цією адресою, яке значення? Якесь значення? Це значення є постійним, ви не можете змінити це значення, але куди вказує вказівник? Якась адреса правда? Це може вказувати і на іншу адресу.

Щоб зрозуміти це, давайте розглянемо нижче код:

#include<stdio.h>
int main()
{
        int num = 300;
        const int *ptr;//constant value, address is modifible
        ptr = &num;
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//
//      *++ptr;//possible bcz you are trying to change address which is possible
//      *(ptr)++;//possible
//      *(++ptr);//possible

//      ++*ptr;//not possible bcz you trying to change value which is not allowed
//      (*ptr)++;//not possible
//      ++(*ptr);//not possible

        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

Спробуйте проаналізувати вихід вищезгаданого коду

2) int const * p : це називається ' **constant pointe**r', тобто address is constant but value is not constant. Тут вам заборонено змінювати адресу, але ви можете змінити значення.

Примітка : постійний вказівник (вищий регістр) повинен ініціалізуватися під час декларування себе.

Щоб зрозуміти це, давайте перевірити простий код.

#include<stdio.h>
int main()
{
        int x = 300;
        int* const p;
        p = &x;
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

У наведеному вище коді, якщо ви помітите, що немає ++ * p або * p ++, ви можете подумати, що це простий випадок, оскільки ми не змінюємо адресу чи значення, але це призведе до помилки. Чому? Причину я згадую в коментарях.

#include<stdio.h>
int main()
{
        int x = 300;
        /** constant pointer must initialize while decaring itself **/
        int* const p;//constant pointer i.e its pointing to some address(here its pointing to garbage), it should point to same address(i.e garbage ad
dress only 
        p = &x;// but here what we are doing ? we are changing address. we are making p to point to address of x instead of garbage address.
        printf("x = %d p =%p and *p = %d\n",num,p,*p);
}

Отже, що вирішує цю проблему?

     int* const p = &x;

Детальніше про цей випадок розглянемо нижче на прикладі.

#include<stdio.h>
int main()
{
        int num = 300;
        int *const ptr = &num;//constant value, address is modifible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
//      *++ptr;//not possible bcz you are trying to change address which is not possible
//      *(ptr)++;//not possible
//      *(++ptr);//not possible

//      ++*ptr;// possible bcz you trying to change value which is allowed
//      (*ptr)++;// possible
//      ++(*ptr);// possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

3) const int * const p : Тут і адреса, і значення є постійними .

Щоб зрозуміти це, давайте перевірити код нижче

#include<stdio.h>
int main()
{
        int num = 300;
        const int* const ptr = &num;//constant value,constant address 
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
        *ptr++;//not possible
        ++*ptr;//not possible
        printf(" num = %d ptr = %p and data on ptr : %d \n",num,ptr,*ptr);
}

-1
const char *p = "Hello";   

*p means "Hello"
          ^
          | 
          p

*p++ means "Hello"
             ^
             | 
             p

*++p means "Hello"
            ^
            |     (WHILE THE STATEMENT IS EXECUTED)
            p

*++p means "Hello"
             ^
             |     (AFTER THE STATEMENT IS EXECUTED)
             p

++*pозначає, що ви намагаєтеся збільшити значення ASCII *pякого

   is "Hello"
       ^
       | 
       p

ви не можете збільшувати значення, тому що воно є постійним, тому ви отримаєте помилку

що стосується циклу while, цикл працює, поки не *p++досягне кінця рядка, де є '\0'символ (NULL).

Тепер, *p++пропускаючи перший символ, ви отримаєте лише вихід, починаючи з другого символу.

Наступний код не видасть нічого, тому що, поки цикл є '\0'

const char *p = "Hello";
    while('\0') 
         printf("%c",*p);

Наступний код дасть вам такий же вихід, як і наступний код, тобто ello.

const char *p = "Hello";
    while(*++p)
         printf("%c",*p);

….

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.