Ekspresi pointer: * ptr ++, * ++ ptr dan ++ * ptr


128

Baru-baru ini saya menemukan masalah yang tidak dapat saya pahami sendiri.

Apa arti ketiga Ekspresi ini BENAR - BENAR ?

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

Saya sudah mencoba Ritchie. Namun sayangnya tidak dapat mengikuti apa yang dia katakan tentang 3 operasi ini.

Saya tahu mereka semua dilakukan untuk meningkatkan pointer / nilai yang ditunjukkan. Saya juga bisa menebak mungkin ada banyak hal tentang prioritas dan urutan evaluasi. Seperti satu penambahan pointer pertama kemudian mengambil konten pointer itu, satu hanya mengambil konten dan kemudian menambah pointer dll. Seperti yang Anda lihat, saya tidak memiliki pemahaman yang jelas tentang operasi aktual mereka , yang saya ingin jelas sesegera mungkin. Tetapi saya benar-benar bingung ketika saya mendapat kesempatan untuk menerapkannya dalam program. Sebagai contoh:

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

memberi saya hasil ini:

ello

Tapi harapan saya adalah bahwa itu akan dicetak Hello. Satu permintaan terakhir - Tolong beri saya contoh untuk bagaimana setiap ekspresi bekerja dalam potongan kode yang diberikan. Karena sebagian besar waktu hanya paragraf teori belaka yang terbang di atas kepala saya.


6
Anda melewatkan yang keempat: (*ptr)++(tanda kurung diperlukan untuk disambiguasi dari *ptr++)
user4815162342

15
Karena Anda menambah pointer sebelum Anda mencetaknya. Anda ingin while (* p) dan printf ("% c", * p ++);
dcaswell

Pertanyaan bagus untuk wawancara. Penggunaan praktis terbatas. Saya berharap C tidak memiliki petunjuk itu :)
Himanshu

5
@ Himanshu Jika itu membuat mie yang Anda wawancarai coba ini: Miliki penunjuk globalchar* p ,, sambil menunjuk ke string karakter unik yang dihentikan yang valid. Kemudian memiliki fungsi fn(char ch)yang mencetak kedua yang chparameter dan char saat ini ditunjuk oleh p. Sekarang panggil fn(*p++);Q: Apakah fnmencetak karakter yang sama dua kali ? Anda akan kagum dengan banyaknya profesor yang salah menjawab pertanyaan itu.
WhozCraig

1
karena p menunjuk ke string literal Anda harus menulisconst char* p = "Hello";
hetepeperfan

Jawaban:


275

Inilah penjelasan terperinci yang saya harap akan membantu. Mari kita mulai dengan program Anda, karena ini adalah yang paling sederhana untuk dijelaskan.

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

Pernyataan pertama:

const char* p = "Hello";

mendeklarasikan psebagai pointer ke char. Ketika kita mengatakan "pointer to a char", apa artinya itu? Ini berarti bahwa nilai padalah alamat a char; pmemberitahu kita di mana di memori ada beberapa ruang yang disisihkan untuk menampung char.

Pernyataan ini juga menginisialisasi puntuk menunjuk ke karakter pertama dalam string literal "Hello". Demi latihan ini, penting untuk dipahami psebagai menunjuk bukan ke seluruh string, tetapi hanya untuk karakter pertama 'H',. Bagaimanapun, padalah pointer ke satu char, bukan ke seluruh string. Nilai padalah alamat 'H'in "Hello".

Kemudian Anda mengatur lingkaran:

while (*p++)

Apa arti dari kondisi loop *p++? Tiga hal sedang dikerjakan di sini yang membuat ini membingungkan (setidaknya sampai keakraban muncul):

  1. Diutamakan dari dua operator, postfix ++dan tipuan*
  2. Nilai ekspresi kenaikan postfix
  3. Efek samping dari ekspresi kenaikan postfix

1. Diutamakan . Pandangan sekilas pada tabel presedensi untuk operator akan memberi tahu Anda bahwa kenaikan postfix memiliki prioritas lebih tinggi (16) daripada dereferensi / tipuan (15). Ini berarti bahwa ekspresi kompleks *p++akan dikelompokkan sebagai: *(p++). Artinya, *bagian itu akan diterapkan pada nilai p++bagian itu. Jadi mari kita ambil p++bagian dulu.

2. Nilai ekspresi postfix . Nilai p++adalah nilai p sebelum kenaikan . Jika Anda memiliki:

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

hasilnya adalah:

7
8

karena i++mengevaluasi isebelum kenaikan. Demikian pula p++akan mengevaluasi dengan nilai saat ini p. Seperti yang kita ketahui, nilai saat ini padalah alamat 'H'.

Jadi sekarang p++bagian dari *p++telah dievaluasi; ini adalah nilai saat ini p. Kemudian *bagian itu terjadi. *(current value of p)berarti: mengakses nilai di alamat yang dipegang oleh p. Kami tahu bahwa nilai di alamat itu adalah 'H'. Jadi ekspresi *p++dievaluasi menjadi 'H'.

Tunggu sebentar, katamu. Jika *p++dievaluasi 'H', mengapa itu tidak 'H'dicetak dalam kode di atas? Di situlah efek samping masuk.

3. Efek samping ekspresi postfix . Postfix ++memiliki nilai operan saat ini, tetapi memiliki efek samping dari penambahan operan itu. Hah? Lihatlah intkode itu lagi:

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

Seperti disebutkan sebelumnya, hasilnya adalah:

7
8

Ketika i++dievaluasi pada yang pertama printf(), ia dievaluasi menjadi 7. Tetapi standar C menjamin bahwa pada titik tertentu sebelum yang kedua printf()mulai dijalankan, efek samping dari ++operator akan terjadi. Artinya, sebelum yang kedua printf()terjadi, iakan bertambah sebagai hasil dari ++operator di yang pertama printf(). Omong-omong, ini adalah salah satu dari sedikit jaminan yang diberikan standar tentang waktu efek samping.

Di kode Anda, kemudian, ketika ekspresi *p++dievaluasi, ia mengevaluasi ke 'H'. Tetapi pada saat Anda sampai pada ini:

printf ("%c", *p)

bahwa efek samping sial telah terjadi. ptelah bertambah. Wah! Itu tidak lagi menunjuk ke 'H', tetapi ke satu karakter masa lalu 'H': ke 'e', dengan kata lain. Itu menjelaskan hasil yang dikhianati:

ello

Oleh karena itu paduan suara saran yang membantu (dan akurat) di jawaban lain: untuk mencetak Pengucapan yang Diterima "Hello"dan bukan mitra cockney-nya, Anda memerlukan sesuatu seperti

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

Sangat banyak untuk itu. Bagaimana dengan yang lainnya? Anda bertanya tentang arti dari ini:

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

Kami hanya berbicara tentang yang pertama, jadi mari kita lihat ini di kedua: *++ptr.

Kami melihat dalam penjelasan kami sebelumnya bahwa kenaikan postfix p++memiliki prioritas , nilai , dan efek samping tertentu . Peningkatan awalan ++pmemiliki efek samping yang sama dengan postfix-nya: ia meningkatkan operandnya dengan 1. Namun, ia memiliki prioritas yang berbeda dan nilai yang berbeda .

Peningkatan awalan memiliki prioritas lebih rendah daripada postfix; ia memiliki diutamakan 15. Dengan kata lain, ia memiliki prioritas yang sama dengan operator dereference / indirection *. Dalam ungkapan suka

*++ptr

yang penting bukanlah yang diutamakan: kedua operator identik dalam hal yang diutamakan. Jadi associativity menendang masuk. Peningkatan awalan dan operator tipuan memiliki associativity kanan-kiri. Karena asosiatif itu, operan ptrakan dikelompokkan dengan operator paling kanan ++sebelum operator lebih ke kiri *,. Dengan kata lain, ekspresi akan dikelompokkan *(++ptr). Jadi, seperti halnya *ptr++tetapi untuk alasan yang berbeda, di sini juga *bagian akan diterapkan pada nilai ++ptrbagian.

Jadi apa nilainya? Nilai ekspresi kenaikan awalan adalah nilai operan setelah kenaikan . Ini membuatnya menjadi binatang yang sangat berbeda dari operator kenaikan postfix. Katakanlah Anda memiliki:

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

Outputnya adalah:

8
8

... berbeda dari yang kami lihat dengan operator postfix. Demikian pula, jika Anda memiliki:

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++

hasilnya adalah:

H e e l                // good dog

Apakah kamu melihat mengapa?

Sekarang kita sampai pada ekspresi ketiga yang Anda tanyakan ++*ptr,. Sebenarnya itu yang paling sulit di antara semuanya. Kedua operator memiliki prioritas yang sama, dan asosiasi kiri-kanan. Ini berarti ekspresi akan dikelompokkan ++(*ptr). Bagian ++akan diterapkan pada nilai *ptrbagian tersebut.

Jadi, jika kita memiliki:

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

hasil yang mengejutkan dari egoisme adalah:

I

Apa?! Oke, jadi *pbagian itu akan dievaluasi 'H'. Kemudian ++permainan mulai, pada titik mana, itu akan diterapkan ke 'H', bukan ke pointer sama sekali! Apa yang terjadi ketika Anda menambahkan 1 'H'? Anda mendapatkan 1 ditambah nilai ASCII 'H', 72; Anda mendapatkan 73. Menyatakan bahwa sebagai char, dan Anda mendapatkan chardengan nilai ASCII dari 73: 'I'.

Itu menangani tiga ekspresi yang Anda tanyakan dalam pertanyaan Anda. Ini yang lain, disebutkan dalam komentar pertama untuk pertanyaan Anda:

(*ptr)++ 

Yang itu juga menarik. Jika Anda memiliki:

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

itu akan memberi Anda hasil yang antusias ini:

HI

Apa yang sedang terjadi? Sekali lagi, ini masalah prioritas , nilai ekspresi , dan efek samping . Karena tanda kurung, *pbagian diperlakukan sebagai ekspresi utama. Ekspresi primer mengalahkan segalanya; mereka dievaluasi terlebih dahulu. Dan *p, seperti yang Anda tahu, mengevaluasi 'H'. Sisa ekspresi, ++bagian, diterapkan ke nilai itu. Jadi, dalam hal ini, (*p)++jadilah 'H'++.

Apa nilainya 'H'++? Jika Anda mengatakan 'I', Anda sudah lupa (sudah!) Diskusi kami tentang nilai vs efek samping dengan kenaikan postfix. Ingat, 'H'++evaluasi dengan nilai saat ini dari 'H' . Jadi yang pertama printf()akan dicetak 'H'. Kemudian, sebagai efek samping , itu 'H'akan bertambah 'I'. Yang kedua printf()mencetak itu 'I'. Dan Anda memiliki ucapan ceria.

Baiklah, tetapi dalam dua kasus terakhir, mengapa saya perlu

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

Kenapa aku tidak bisa memiliki sesuatu seperti itu

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

Karena "Hello"merupakan string literal. Jika Anda mencoba ++*p, Anda mencoba mengubah 'H'string ke 'I', membuat keseluruhan string "Iello". Dalam C, string literal hanya-baca; mencoba memodifikasinya memunculkan perilaku yang tidak jelas. "Iello"tidak terdefinisi dalam bahasa Inggris juga, tapi itu hanya kebetulan.

Sebaliknya, Anda tidak bisa

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

Kenapa tidak? Karena dalam contoh ini, padalah array. Array bukan nilai-l yang dapat dimodifikasi; Anda tidak dapat mengubah di mana ppoin dengan kenaikan sebelum atau sesudah kenaikan atau penurunan, karena nama array berfungsi seolah-olah itu adalah pointer konstan. (Bukan itu sebenarnya; itu hanya cara yang nyaman untuk melihatnya.)

Singkatnya, berikut adalah tiga hal yang Anda tanyakan:

*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

Dan inilah yang keempat, setiap kesenangan sebanyak tiga lainnya:

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

Yang pertama dan kedua akan crash jika ptrsebenarnya merupakan pengidentifikasi array. Yang ketiga dan keempat akan crash jika ptrmenunjuk ke string literal.

Itu dia. Saya harap semuanya kristal sekarang. Anda telah menjadi pendengar yang hebat, dan saya akan berada di sini sepanjang minggu.


22
Sebelum datang ke forum ini, saya telah mencari 3 buku "C" yang saya miliki. Saya juga sudah mencoba beberapa tutorial online terkenal. Tetapi tidak satu pun dari mereka yang mendekati penjelasan Anda (terutama cara Anda menggabungkan semuanya). Anda tidak hanya menjawab pertanyaan yang saya ajukan, tetapi juga Anda telah membahas lebih banyak hal dari tingkat akar rumput. Sebenarnya Anda telah mengajari saya banyak hal dasar hari ini, yang tidak saya miliki sebelumnya. Saya tidak bisa membantu tetapi mengalihkan jawaban yang saya terima. :) Terima kasih lagi.
dialokasikan

26
+1 Saya pikir ini adalah jawaban panjang terbaik yang pernah saya baca di SO. Saya pikir semua orang bisa belajar banyak dari jawaban ini.
Shafik Yaghmour

9
Anda Tuan, harus menulis buku tentang C.
Dillon Burton

1
Sungguh jawaban yang bagus untuk pertanyaan yang bagus! @Verbose bagus!
benka

7
@lagi Anda, Tuan, hidup sesuai dengan nama Anda .. :)
sleeping_dragon

44

Misalkan ptrmenunjuk ke elemen array ke-i arr.

  1. *ptr++mengevaluasi ke arr[i]dan set ptruntuk menunjuk ke elemen (i +1) dari arr. Ini setara dengan *(ptr++).

  2. *++ptrset ptruntuk menunjuk ke elemen (i +1) arrdan mengevaluasi ke arr[i+1]. Ini setara dengan *(++ptr).

  3. ++*ptrmeningkat arr[i]satu dan mengevaluasi nilainya meningkat; pointer ptrdibiarkan tak tersentuh. Ini setara dengan ++(*ptr).

Ada juga satu lagi, tetapi Anda membutuhkan tanda kurung untuk menuliskannya:

  1. (*ptr)++bertambah arr[i]satu dan mengevaluasi nilainya sebelum ditingkatkan; pointer ptrlagi dibiarkan tak tersentuh.

Sisanya, Anda bisa mengetahui sendiri; itu juga dijawab oleh @Jaguar.


13

*ptr++ : post increment a pointer ptr

*++ptr : Pre Increment a pointer ptr

++*ptr : preincrement the value at ptr location

Baca di sini tentang operator kenaikan sebelum dan sesudah kenaikan


Ini akan memberikan Hellosebagai output

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

@ Nik-Lz Ya, hasilnya adalahHello
Jainendra

7

Kondisi dalam loop Anda buruk:

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

Sama dengan

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

Dan itu salah, ini seharusnya:

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

*ptr++sama dengan *(ptr++), yaitu:

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

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

*++ptrsama dengan *(++ptr), yaitu:

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

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

++*ptrsama dengan ++(*ptr), yaitu:

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

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

Saya akan sangat setuju dengan bagian pertama dari jawabannya. Pada bagian kedua, menginisialisasi pointer (ke integer!) Dengan integer membingungkan bagi seseorang yang berjuang untuk memahami penggunaan pointer.
nickie

4

Anda benar tentang prioritas, perhatikan bahwa *prioritas lebih tinggi daripada kenaikan awalan, tetapi tidak lebih dari kenaikan postfix. Begini cara pemecahannya:

*ptr++ - pergi dari kiri ke kanan, melakukan dereferensi pointer, dan kemudian meningkatkan nilai pointer (bukan apa yang ditunjukkan, karena didahulukan dari postfix atas dereference)

*++ptr - increment the pointer dan kemudian dereference, ini karena awalan dan dereference memiliki prioritas yang sama dan mereka dievaluasi dalam urutan kanan-ke-kiri

++*ptr- mirip dengan yang di atas dalam hal presedensi, sekali lagi pergi dari kanan ke kiri dalam rangka dereferensi pointer dan kemudian meningkatkan apa yang menunjuk pointer. Harap perhatikan bahwa dalam kasus Anda, ini akan menyebabkan perilaku tidak terdefinisi karena Anda mencoba mengubah variabel read-only ( char* p = "Hello";).


3

Saya akan menambahkan pendapat saya karena sementara jawaban lainnya benar saya pikir mereka kehilangan sesuatu.

 v = *ptr++

cara

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

Dimana sebagai

 v = *++ptr

cara

 ptr = ptr + 1
 v   = *ptr

Sangat penting untuk memahami bahwa kenaikan pasca (dan pasca penurunan) berarti

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

Mengapa itu penting? Nah di C itu tidak begitu penting. Dalam C + + ptrmungkin tipe kompleks seperti iterator. Sebagai contoh

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

Dalam hal ini, karena itjenis yang kompleks it++mungkin memiliki efek samping karena temppembuatannya. Tentu saja jika Anda beruntung, kompiler akan mencoba untuk membuang kode yang tidak diperlukan tetapi jika konstruktor atau destruktor iterator melakukan apa pun maka it++akan menunjukkan efek tersebut ketika dibuat temp.

Pendek dari apa yang saya coba katakan adalah Write What You Mean . Jika Anda maksud ptr kenaikan maka tulis ++ptrtidak ptr++. Jika Anda maksud temp = ptr, ptr += 1, tempmaka tulislahptr++


0
*ptr++    // 1

Ini sama dengan:

    tmp = *ptr;
    ptr++;

Jadi nilai objek yang ditunjuk oleh ptrdiambil, lalu ptrditambahkan.

*++ptr    // 2

Ini sama dengan:

    ++ptr;
    tmp = *ptr;

Jadi pointer ptrbertambah, maka objek yang ditunjuk oleh ptrdibaca.

++*ptr    // 3

Ini sama dengan:

    ++(*ptr);

Jadi objek yang ditunjuk oleh ptrbertambah; ptritu sendiri tidak berubah.


0

postfix dan prefix memiliki prioritas lebih tinggi daripada dereference

* ptr ++ di sini memposting kenaikan ptr dan kemudian menunjuk ke nilai ptr baru

* ++ ptr di sini Tinju Pra Peningkatan kemudian menunjuk ke nilai baru ptr

++ * ptr di sini pertama-tama mendapatkan nilai ptr menunjuk ke dan meningkatkan vlaue itu


1
Ini salah. Postfix memiliki prioritas lebih tinggi, tetapi awalan memiliki prioritas yang sama dengan dereference.
verbose

0

Ekspresi Pointer: * ptr ++, * ++ ptr dan ++ * ptr:

Catatan : pointer harus diinisialisasi dan harus memiliki alamat yang valid. Karena dalam RAM selain dari program kami (a.out) ada banyak lagi program yang berjalan secara bersamaan yaitu jika Anda mencoba mengakses beberapa memori yang tidak dicadangkan untuk OS Anda akan melalui kesalahan Segmentasi.

Sebelum menjelaskan ini, mari pertimbangkan contoh sederhana?

#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);
}

menganalisis output dari kode di atas, saya harap Anda mendapatkan output dari kode di atas. Satu hal yang jelas dari kode di atas adalah bahwa nama penunjuk ( ptr ) berarti kita berbicara tentang alamat dan * ptr berarti kita berbicara tentang nilai / data.

KASUS 1 : * ptr ++, * ++ ptr, * (ptr ++) dan * (++ ptr):

Semua sintaks yang disebutkan di atas mirip, dalam semua address gets incrementedtapi bagaimana alamat bertambah itu berbeda.

Catatan : untuk menyelesaikan ekspresi apa pun, cari tahu berapa banyak operator yang ada dalam ekspresi, kemudian cari tahu prioritas operator. Saya beberapa operator memiliki prioritas yang sama kemudian memeriksa urutan evolusi atau asosiasi yang dapat kanan (R) ke kiri (L) atau kiri ke kanan.

* ptr ++ : Di sini ada 2 operator yaitu de-reference (*) dan ++ (increment). Keduanya memiliki prioritas yang sama kemudian memeriksa asosiatif yaitu R to L. Jadi, mulailah menyelesaikan dari Kanan ke Kiri, operator apa pun yang lebih dulu.

* ptr ++ : first ++ datang sambil menyelesaikan dari R ke L, jadi alamat bertambah tetapi post kenaikannya.

* ++ ptr : Sama seperti yang pertama di sini juga alamat bertambah tetapi kenaikannya sebelum.

* (ptr ++) : Di sini ada 3 operator, di antaranya pengelompokan () yang memiliki prioritas tertinggi, Jadi ptr ++ pertama yang dipecahkan yaitu alamat akan bertambah tetapi dikirim.

* (++ ptr) : Sama seperti kasus di atas di sini juga alamat akan bertambah tetapi sebelum kenaikan.

KASUS 2 : ++ * ptr, ++ (* ptr), (* ptr) ++:

Semua sintaks yang disebutkan di atas serupa, dalam semua nilai / data bertambah tetapi bagaimana nilai diubah yang berbeda.

++ * ptr : first * datang sambil menyelesaikan dari R ke L, jadi nilainya berubah tetapi kenaikannya sebelum.

++ (* ptr) : Sama seperti huruf di atas, nilainya diubah.

(* ptr) ++ : Di sini ada 3 operator, di antaranya pengelompokan () memiliki prioritas tertinggi, Inside () * ptr ada, Jadi pertama * ptr diselesaikan yaitu nilai bertambah tetapi posting.

Catatan : ++ * ptr dan * ptr = * ptr + 1 keduanya sama, dalam kedua nilai kasus akan berubah. ++ * ptr: hanya 1 instruksi (INC) yang digunakan, nilai langsung akan berubah dalam satu tembakan. * ptr = * ptr + 1: di sini nilai pertama akan bertambah (INC) dan kemudian ditugaskan (MOV).

Untuk memahami semua sintaks kenaikan yang berbeda pada pointer, mari pertimbangkan kode sederhana ini:

#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);
}

Dalam kode di atas, cobalah untuk mengomentari / membatalkan komentar komentar dan menganalisis output.

Pointer sebagai Constant : tidak ada cara dimana Anda dapat menjadikan pointer sebagai konstan, hanya sedikit yang saya sebutkan di sini.

1) const int * p OR int const * p : Berikut valueadalah konstan , alamat tidak konstan yaitu dimana p menunjuk? Beberapa alamat? Pada alamat itu berapa nilainya? Beberapa nilai bukan? Nilai itu konstan, Anda tidak bisa mengubah nilai itu tetapi di mana pointer menunjuk? Beberapa alamat bukan? Itu bisa menunjuk ke alamat lain juga.

Untuk memahami ini, mari pertimbangkan kode di bawah ini:

#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);
}

Cobalah untuk menganalisis output dari kode di atas

2) int const * p : itu disebut **constant pointe**r'yaitu address is constant but value is not constant. Di sini Anda tidak diperbolehkan mengubah alamat tetapi Anda dapat mengubah nilainya.

Catatan : pointer konstan (huruf di atas) harus menginisialisasi sambil menyatakan sendiri.

Untuk memahami ini mari kita periksa kode sederhana.

#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);
}

Dalam kode di atas, jika Anda mengamati bahwa tidak ada ++ * p atau * p ++ Jadi Anda mungkin berpikir ini adalah kasus sederhana karena kami tidak mengubah alamat atau nilai tetapi akan menghasilkan kesalahan. Mengapa Alasan saya sebutkan dalam komentar.

#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);
}

Jadi, apa solusi dari masalah ini?

     int* const p = &x;

untuk lebih lanjut tentang kasus ini mari kita perhatikan contoh di bawah ini.

#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 : Di sini alamat dan nilainya konstan .

Untuk memahami ini mari kita periksa kode di bawah ini

#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

++*pberarti Anda mencoba untuk menambah nilai ASCII *pyang mana

   is "Hello"
       ^
       | 
       p

Anda tidak dapat menambah nilainya karena ini adalah konstanta sehingga Anda akan mendapatkan kesalahan

Sedangkan untuk loop sementara Anda, loop berjalan hingga *p++mencapai ujung string di mana ada karakter '\0'(NULL).

Sekarang karena *p++melompati karakter pertama Anda hanya akan mendapatkan output Anda mulai dari karakter kedua.

Kode berikut tidak akan menghasilkan apa-apa karena while memiliki '\0'

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

Kode berikut akan memberi Anda output yang sama dengan kode berikutnya yaitu ello.

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

...................................

const char *p = "Hello";
    while(*p++)
         printf("%c",*p);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.