#include <stdio.h>
#include <stdlib.h>

int* test(int); // the prototype

int main()
{
    int var = -20;
    int *ptr = NULL;
    ptr = test(var);
    printf("This is what we got back in main(): %d \n", *ptr);
    return 0;
}

int* test(int k)
{
    int y = abs(k);
    int *ptr1 = &y;
    printf("The value of y in test() directly is %d \n", y);
    printf("The value of y in test() indirectly is %d \n", *ptr1);
    return ptr1;
}
The output is:
The value of y in test() directly is 20
The value of y in test() indirectly is 20
This is what we got back in main(): 20

Ringkasan Singkat: Kode yang disebutkan di atas memiliki fungsi yang ditentukan pengguna yang mengembalikan pointer yang menyimpan alamat variabel (yaitu, y). Variabel ini diberi nilai absolut dari integer yang diteruskan ke fungsi (yaitu, x)

Buku saya " Pemrograman Komputer untuk Pemula" oleh A.J.Gonzalez menyatakan sebagai berikut: Variabel y akan tidak ada lagi setelah fungsi keluar, sehingga alamat yang dikembalikan ke fungsi panggilan akan menjadi tidak berarti. Namun nilai yang disimpan di alamatnya akan tetap ada dan dapat diambil melalui pointer.

Pertanyaanku adalah : Bagaimana kami sampai pada kesimpulan ini bahwa nilai yang disimpan di alamat akan tetap ada dan dapat diambil melalui penunjuk dari pernyataan printf berikut:

Pernyataan pertama: memberi nilai secara langsung menggunakan y.

Pernyataan ke-2: menggunakan pointer untuk memberikan nilai.

Pernyataan ke-3: mendapatkan nilai dari main.

Semua itu baik-baik saja tetapi kemudian dari sana bagaimana seseorang membuat kesimpulan bahwa variabel penggunaan langsung kehilangan nilainya tetapi variabel yang digunakan secara tidak langsung (yaitu, pointer) mempertahankan nilainya? Saya mencoba melihat pertanyaan sebelumnya tetapi tidak dapat menemukan sesuatu yang relevan.

Akan berterima kasih atas bantuan Anda. Terima kasih.

2
watercolour man 25 Mei 2021, 15:56

3 jawaban

Jawaban Terbaik

Program ini mengilustrasikan efek dari perilaku tidak terdefinisi.

Setelah test kembali, nilai pointer yang dikembalikannya menunjuk ke variabel yang tidak ada lagi. Secara formal, ini adalah perilaku tidak terdefinisi yang berarti bahwa standar C tidak menjamin apa yang akan terjadi ketika Anda mencoba menggunakan pointer ini. Dalam prakteknya, memori yang digunakan oleh y belum ditimpa oleh beberapa nilai lain sehingga dereferensi pointer akan sering menghasilkan nilai yang disimpan di sana.

Tapi sekali lagi, tidak ada jaminan itu akan benar-benar terjadi. Sebagai contoh, jika kita mengubah fungsi main sebagai berikut:

int main()
{
    int var = -20;
    int *ptr = NULL;
    ptr = test(var);
    printf("This is what we got back in main(): %d \n", *ptr);
    printf("%d %d %d %f\n", 1, 2, 3, 4.0);
    printf("This is what we got back in main(): %d \n", *ptr);
    return 0;
}

Output mesin saya:

The value of y in test() directly is 20 
The value of y in test() indirectly is 20 
This is what we got back in main(): 20 
1 2 3 4.000000
This is what we got back in main(): 0 

Yang menunjukkan bahwa memori yang sebelumnya digunakan oleh y memiliki nilai lain.

Moral dari cerita ini: jangan mencoba menggunakan pointer ke variabel yang sudah tidak ada lagi.

4
dbush 25 Mei 2021, 13:09

Alasan buku ini agak benar, namun mengasumsikan arsitektur yang mendorong parameter ke tumpukan, seperti Intel.

Apa yang terjadi adalah lokasi y tidak digunakan kembali sampai setelah nilainya diambil melalui ptr dari main untuk didorong ke tumpukan untuk panggilan printf.

Namun, interupsi dapat menggunakan kembali lokasi dan secara umum ini adalah perilaku tidak terdefinisi.

Catatan: ini digunakan oleh kompiler saat mengembalikan struct sebagai pengembalian fungsi. Kompilator menyalin variabel struct dari fungsi yang dipanggil ke struct pemanggil, sebelum hal lain terjadi, sehingga memori belum digunakan kembali.

1
Paul Ogilvie 25 Mei 2021, 13:14

Pertanyaan saya adalah: Bagaimana kami sampai pada kesimpulan ini bahwa nilai yang disimpan di alamat akan bertahan dan dapat diambil melalui pointer

Fungsi mengembalikan alamat tempat variabel digunakan untuk disimpan, kemungkinan besar di suatu tempat di tumpukan. Tetapi karena alamat tersebut tidak lagi valid, maka isi pointer sekarang adalah tidak tentu. Artinya tidak ada jaminan apa-apa lagi. Dan Anda tidak dapat mereferensikan pointer itu lagi, kode ini disadap:

printf("This is what we got back in main(): %d \n", *ptr);

Itu bisa mencetak apa pun atau menyebabkan crash program, ini disebut "perilaku tidak terdefinisi" (sesuai standar C C17 6.2.4/2), lihat Apa itu perilaku tidak terdefinisi dan bagaimana cara kerjanya?.

Kesimpulan apa yang bisa kita tarik dari ini? Hanya satu, mengembalikan pointer ke variabel lingkup lokal dari suatu fungsi adalah buruk dan bug.

Selain itu, tidak ada alasan lain, tidak ada perilaku deterministik, tidak ada fenomena menarik untuk dipelajari atau dipelajari sesuatu yang bermakna. Lihat Dapatkah memori variabel lokal diakses di luar cakupannya?

1
Lundin 25 Mei 2021, 13:10