Berapa banyak pointer ( *
) yang diizinkan dalam satu variabel?
Mari kita perhatikan contoh berikut ini.
int a = 10;
int *p = &a;
Demikian pula yang bisa kita miliki
int **q = &p;
int ***r = &q;
dan seterusnya.
Sebagai contoh,
int ****************zz;
std::shared_ptr<shared_ptr<shared_ptr<...shared_ptr<int>...>>>
(pow (std::shared_ptr, -0.3))<T> x;
untuk -0,3 tingkat tipuan.Jawaban:
The
C
menspesifikasikan standar batas bawah:Batas atas adalah implementasi khusus.
sumber
typedef
s.Sebenarnya, program C umumnya menggunakan tipuan pointer tak terbatas. Satu atau dua level statis adalah umum. Tiga tipuan jarang terjadi. Tetapi tak terbatas sangat umum.
Peniruan penunjuk tak terbatas dicapai dengan bantuan struct, tentu saja, tidak dengan deklarator langsung, yang tidak mungkin dilakukan. Dan sebuah struct diperlukan agar Anda dapat memasukkan data lain dalam struktur ini pada level yang berbeda di mana ini dapat berakhir.
sekarang kamu bisa punya
list->next->next->next->...->next
. Ini benar-benar hanya beberapa indirections pointer:*(*(..(*(*(*list).next).next).next...).next).next
. Dan pada.next
dasarnya adalah noop ketika itu adalah anggota pertama dari struktur, jadi kita bisa membayangkan ini sebagai***..***ptr
.Sebenarnya tidak ada batasan untuk ini karena tautan dapat dilalui dengan loop daripada ekspresi raksasa seperti ini, dan terlebih lagi, struktur dapat dengan mudah dibuat melingkar.
Dengan demikian, dengan kata lain, daftar tertaut dapat menjadi contoh utama untuk menambahkan tingkat tipuan lain untuk menyelesaikan masalah, karena Anda melakukannya secara dinamis dengan setiap operasi push. :)
sumber
list->next
danlist->next->next
merupakan tipe yang sama; jika tidak, kita harus membangun tipe infinite.)LOAD R1, [R1]
selama R1 adalah pointer yang valid di setiap langkah. Tidak ada tipe yang terlibat selain "kata yang menyimpan alamat". Ada atau tidaknya tipe yang dideklarasikan tidak menentukan tipuan dan berapa level yang dimilikinya.R1
memegang alamat lokasi yang menunjuk ke dirinya sendiri makaLOAD R1, [R1]
dapat dieksekusi dalam loop tak terbatas.Secara teoretis:
Anda dapat memiliki banyak tingkat tipuan yang Anda inginkan.
Praktis:
Tentu saja, tidak ada yang mengkonsumsi memori yang tidak dapat ditentukan, akan ada keterbatasan karena sumber daya yang tersedia di lingkungan host. Jadi praktis ada batas maksimum untuk apa suatu implementasi dapat mendukung dan implementasi harus mendokumentasikannya dengan tepat. Jadi dalam semua artefak tersebut, standar tidak menentukan batas maksimum, tetapi menentukan batas bawah.
Inilah rujukannya:
C99 Standar 5.2.4.1 Batas terjemahan:
Ini menentukan batas bawah yang harus didukung oleh setiap implementasi . Perhatikan bahwa dalam catatan kaki standar lebih lanjut mengatakan:
sumber
*
kelebihan beban untuk sejumlah kelas berturut-turut, dan masing-masing kelebihan mengembalikan objek jenis lain di baris, maka bisa ada stackoverflow untuk panggilan fungsi berantai seperti itu.Seperti yang dikatakan orang, tidak ada batasan "dalam teori". Namun, karena ketertarikan saya menjalankan ini dengan g ++ 4.1.2, dan bekerja dengan ukuran hingga 20.000. Kompilasi cukup lambat, jadi saya tidak mencoba lebih tinggi. Jadi saya kira g ++ juga tidak menetapkan batas apa pun. (Coba pengaturan
size = 10
dan cari di ptr.cpp jika tidak segera jelas.)g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr
create.cpp
sumber
*
sampai saya mendapatkan satu yang gagal, dan yang sebelumnya berlalu; Saya kemudian melakukan pencarian biner pada interval itu untuk yang pertama yang gagal. Seluruh tes membutuhkan waktu kurang dari satu detik untuk menjalankan.)Kedengarannya menyenangkan untuk diperiksa.
Visual Studio 2010 (pada Windows 7), Anda dapat memiliki level 1011 sebelum mendapatkan kesalahan ini:
gcc (Ubuntu), 100k +
*
tanpa crash! Saya kira perangkat keras adalah batasannya di sini.(diuji hanya dengan deklarasi variabel)
sumber
*
node ke stack sebelum dapat melakukan pengurangan.Tidak ada batasan, periksa contoh di sini .
Jawabannya tergantung pada apa yang Anda maksud dengan "level pointers." Jika Anda maksudkan, "Berapa tingkat tipuan yang dapat Anda miliki dalam satu deklarasi?" jawabannya adalah "Setidaknya 12."
Jika Anda maksudkan, "Berapa banyak level pointer yang dapat Anda gunakan sebelum program sulit dibaca," itu masalah selera, tetapi ada batasnya. Memiliki dua tingkat tipuan (pointer ke pointer ke sesuatu) adalah umum. Lebih dari itu semakin sulit untuk dipikirkan dengan mudah; jangan lakukan itu kecuali jika alternatifnya akan lebih buruk.
Jika Anda maksudkan "Berapa banyak tingkat tipuan pointer yang dapat Anda miliki saat runtime," tidak ada batasan. Titik ini sangat penting untuk daftar bundar, di mana setiap titik menunjuk ke yang berikutnya. Program Anda dapat mengikuti petunjuk selamanya.
sumber
g++
dibatalkan dengan kesalahan internal pada 98242 pada mesin saya. Saya berharap bahwa batas aktual akan tergantung pada mesin dan beban. Saya juga tidak berharap ini menjadi masalah dalam kode nyata.)circ_list
contoh mengenai pertanyaan OP: Fakta bahwa Anda dapat melintasi daftar pointer tidak menyiratkan bahwa kompiler dapat mengkompilasi tipuan bintang n.Ini sebenarnya lebih lucu dengan pointer ke fungsi.
Seperti diilustrasikan di sini, ini memberi:
Dan itu tidak melibatkan overhead runtime, jadi Anda mungkin dapat menumpuknya sebanyak yang Anda inginkan ... sampai kompiler Anda tersedak file.
sumber
Tidak ada batasan . Pointer adalah sepotong memori yang isinya adalah alamat.
Seperti yang Anda katakan
Penunjuk ke penunjuk juga merupakan variabel yang berisi alamat penunjuk lain.
Berikut
q
ini adalah pointer ke pointer memegang alamatp
yang sudah memegang alamata
.Tidak ada yang khusus tentang pointer ke pointer.
Jadi tidak ada batasan pada rantai ponitor yang memegang alamat pointer lain.
yaitu.
Diperbolehkan.
sumber
Setiap pengembang C ++ seharusnya sudah mendengar tentang programmer Bintang Tiga yang terkenal
Dan tampaknya benar-benar ada "penghalang penunjuk" ajaib yang harus disamarkan
sumber
Perhatikan bahwa ada dua pertanyaan yang mungkin di sini: berapa banyak tingkat tipuan pointer yang dapat kita capai dalam tipe C, dan berapa banyak tingkat tipuan pointer yang dapat kita masukkan ke dalam satu deklarator tunggal.
Standar C memungkinkan maksimum untuk dikenakan pada yang pertama (dan memberikan nilai minimum untuk itu). Tapi itu bisa dielakkan melalui beberapa deklarasi typedef:
Jadi pada akhirnya, ini adalah masalah implementasi yang terhubung dengan gagasan tentang seberapa besar / kompleks sebuah program C dapat dibuat sebelum ditolak, yang merupakan kompiler yang sangat spesifik.
sumber
Saya ingin menunjukkan bahwa memproduksi suatu tipe dengan jumlah * yang sewenang-wenang adalah sesuatu yang dapat terjadi dengan metaprogramming template. Saya lupa persis apa yang saya lakukan, tetapi disarankan agar saya dapat menghasilkan tipe berbeda baru yang memiliki beberapa jenis meta manuver di antara mereka dengan menggunakan tipe T * rekursif .
Templat Metaprogramming adalah keturunan yang lambat menuju kegilaan, jadi tidak perlu membuat alasan ketika membuat suatu tipe dengan beberapa ribu level tipuan. Ini hanya cara praktis untuk memetakan bilangan bulat kacang polong, misalnya, ke ekspansi templat sebagai bahasa fungsional.
sumber
Peraturan 17.5 dari standar MISRA C 2004 melarang lebih dari 2 level tipuan pointer.
sumber
"non-compliant"
standar mereka. Kata atau frasa penting dalam keputusan mereka adalah penggunaan kata"should"
dari pernyataan ini:Use of more than 2 levels of indirection can seriously impair the ability to understand the behavior of the code, and should therefore be avoided.
Ini adalah pedoman yang ditetapkan oleh organisasi ini sebagai lawan dari aturan yang ditetapkan oleh standar bahasa.Tidak ada yang namanya batas nyata tetapi ada batas. Semua pointer adalah variabel yang biasanya disimpan dalam stack, bukan heap . Tumpukan biasanya kecil (dimungkinkan untuk mengubah ukurannya selama beberapa penautan). Jadi katakanlah Anda memiliki tumpukan 4MB, apa ukuran yang cukup normal. Dan katakanlah kita memiliki pointer yang berukuran 4 byte (ukuran pointer tidak sama tergantung pada pengaturan arsitektur, target dan kompiler).
Pada kasus ini
4 MB / 4 b = 1024
jumlah maksimum yang memungkinkan adalah 1048576, tetapi kita tidak boleh mengabaikan fakta bahwa beberapa hal lain ada di tumpukan.Namun beberapa kompiler mungkin memiliki jumlah maksimum rantai penunjuk, tetapi batasnya adalah ukuran tumpukan. Jadi, jika Anda meningkatkan ukuran tumpukan selama menghubungkan dengan infinity dan memiliki mesin dengan memori infinity yang menjalankan OS yang menangani memori itu sehingga Anda akan memiliki rantai penunjuk yang tidak terbatas.
Jika Anda menggunakan
int *ptr = new int;
dan meletakkan pointer Anda ke tumpukan, itu tidak batas cara biasa akan menjadi ukuran tumpukan, bukan tumpukan.EDIT Sadarilah itu
infinity / 2 = infinity
. Jika mesin memiliki lebih banyak memori maka ukuran pointer bertambah. Jadi jika memori tak terhingga dan ukuran penunjuk adalah tak terhingga, maka itu adalah berita buruk ... :)sumber
new int*
). B) Anint*
danint**********
memiliki ukuran yang sama, setidaknya pada arsitektur yang masuk akal.int*
danint**********
memiliki ukuran yang sama, saya tidak mengatakan bahwa mereka memiliki perbedaan.Itu tergantung pada tempat Anda menyimpan pointer. Jika mereka berada di tumpukan Anda memiliki batas yang cukup rendah . Jika Anda menyimpannya di tumpukan, batas Anda jauh lebih tinggi.
Lihatlah program ini:
Ini menciptakan pointer 1M dan pada titik menunjukkan ke apa mudah untuk melihat apa rantai pergi ke variabel pertama
number
.BTW. Ini menggunakan
92K
RAM jadi bayangkan seberapa dalam Anda bisa melangkah.sumber