Nima uchun ko'rsatgich deklaratsiyasini umumlashtira olmaymiz?

Pointerning kattaligi, ma'lumotlarga ishora qiluvchi ma'lumotlardan qat'i nazar, bir xil bo'ladi. Nima uchun biz ko'rsatadigan ma'lumot turi haqida ma'lumot berishimiz kerak?

Misol uchun,

int *p;  //p will point to an integer data type.
char *p;  //p will point to a character

Unday bo'lsa, nima uchun bu kabi ko'rsatgich deklaratsiyasini umumlashtira olmaymiz

pointer p;  //where p is an object of pointer class.
4
Men bu savolni mavzudan tashqarida qoldirish uchun ovoz beraman, chunki boshlang'ich jumladagi taxmin noto'g'ri.
qo'shib qo'ydi muallif Bo Persson, manba
@latish Hech bo'lmaganda marker arifmetikasini bajarish uchun sivralangan ob'ekt o'lchamini bilishingiz kerak.
qo'shib qo'ydi muallif Vlad from Moscow, manba
"Ko'rsatkichlar kattaligi, ishora qilayotgan ma'lumotlardan qat'i nazar, xuddi shunday." - Yo'q, yo'q.
qo'shib qo'ydi muallif Neil Butterworth, manba
"Void deb nomlangan umumiy marker bor *" Yarim umumiy - vazifada ishora qilish mumkin emas.
qo'shib qo'ydi muallif Neil Butterworth, manba
void * deb nomlangan umumiy marker mavjud, ammo siz to'g'ridan-to'g'ri kursor arifmetikasini qilolmaysiz. Pointer arifmetikasi ko'rsatgan ob'ektining o'lchamiga bog'liq, bu ko'rsatkich markerning o'zi emas.
qo'shib qo'ydi muallif Nick Frost, manba
Lekin bu faqat o'n oltita sonli manzilni saqlaydi? Nima uchun bunday emas?
qo'shib qo'ydi muallif latish, manba

6 javoblar

TL;DR because, different data types occupy different size in memory and has different alignment requirement.

Taqqoslash uchun marker o'zgaruvchisi ba'zi ma'lumotlarga ishora qiluvchi manzilni o'z ichiga oladi. Aloqada bo'lmagan holda, ko'rsatgichni o'chirish va qiymati ni olishning imkoni yo'q.

Boshqacha qilib aytganda, ko'rsatgich bilan ko'rsatiladigan ma'lumotlarga kirish uchun tegishli ma'lumot turi ma'lum bo'lishi kerak.

Pointerning o'zi o'zi ko'rsatadigan haqiqiy ma'lumotlarga juda oz bog'liqdir.

generic ko'rsatgichi sifatida ko'riladigan void * ko'rsatgichi mavjud, lekin keyinchalik uni bekor qilolmaysiz, chunki natijada natija to'liq bo'lmagan turdagi . Noto'g'ri ko'rsatgich ustida pointer arifmetikini chetlatish yoki qo'llash uchun uni to'liq turga o'tkazishingiz kerak.

void * kodini ko'rib chiqishning sababi generic pointerini C11 standartidan keltirib, quyida §6.3.2.3

void belgisi, markerdan har qanday ob'ekt turiga aylantirilishi mumkin. Ko'rsatgich   har qanday ob'ekt turi void uchun markerga aylantirilishi va yana qaytib kelishi mumkin; natija bo'lishi kerak   asl belgisi bilan taqqoslash.

Shunday qilib, void * har qanday markerni ushlab turadigan umumiy konteyner sifatida ishlatilishi mumkin, ammo markerda (ma'lumotlarni turi ), siz uni avval to'liq turga o'tkazishingiz kerak.

13
qo'shib qo'ydi
OK, har qanday sharh bermasdan ikkita pastga tushirish, men hozir juda qiziqaman. Kimdir?
qo'shib qo'ydi muallif Sourav Ghosh, manba
Nima sababdan tushunmovsiz, pastga tushishdan ko'proq nafratlanadigan hech narsa yo'q. Sizning javobingiz to'g'ridir, mening javobim (agar o'qigan bo'lsangiz) sizning yaxshi qo'shilishingiz bo'lishi mumkin. Lekin sizning ...
qo'shib qo'ydi muallif Tony Tannous, manba

Siz void * yordamida markerlarni umumlashtira olasiz. void * biron bir turdagi ma'lumotsiz birorta manzilga ishora qiladi. Biroq, bu ko'rsatgichlar bilan avval ularni ochiq-oydin ko'rsatgichga yozmasdan qilishingiz mumkin.

Keling, quyidagi misolni ko'rib chiqaylik. Buni tuzishmaydi, chunki ptr bilan ko'rsatilgan "qiymat" ni ifodalash mumkin emas. Qiymatni qancha bayta tashkil etayotganini bilolmaysiz.

void print(const void * ptr) {
    std::cout << *ptr;//What's the "value" of ptr?
}
6
qo'shib qo'ydi
Meni 30 soniya bilan urib yuboring ...
qo'shib qo'ydi muallif Andrew Henle, manba

Pointer arifmetikasi.

Izoh:

int arr[] = {4, 6, 9, 10};
int* x = arr;

*(x+0) = 4
*(x+1) = 6

Compiler biladiki, x + 1 aslida x + sizeof (int) va 1 emas.

Ikkinchi elementni o'qish uchun derleyici hajmiof (int) ni har safar o'tkazib yuborishi kerak. Haqiqiy turni bilmasangiz, uni uzib tashlab, ma'lumotlarni to'g'ri chiqarib olmaysiz.

Plyus turlari hajmi jihatidan farq qiladi va kompilyator xotiradan qanchalik bayt o'qilishini bilishi kerak. Bir char 1 bayt bo'ladi va int 1 bayttan ortiq bo'ladi.

6
qo'shib qo'ydi
Iltimos, batafsilroq ma'lumot bera olasizmi? Men yangi odamman
qo'shib qo'ydi muallif latish, manba

void * markerni "umumiy" ko'rsatgich sifatida ko'rish mumkin.

Biroq, uni yo'q qilish mumkin emas, chunki umumiy bo'lishi bilan u har qanday turdagi narsaga ishora qilmaydi. Haqiqatdan ham dan void * markerni ishlating va nimani ko'rsatgan bo'lsa, kiring, unga kirayotgan ob'ekt turiga ko'chirishingiz kerak.

Va har qanday bir turdagi ob'ektni ko'rsatmasligi uchun void * markeridagi ko'rsatkich ko'rsatkichini bajarishning to'g'ri usuli yo'q.

2
qo'shib qo'ydi
p kodi void bo'lsa, unda * p kodi void hech qanday qiymat - void tugallanmagan tugallanmagan turi va u bilan bog'liq qiymatlar yo'q. Shuning uchun uni boshqa usulda o'zgartirishingiz kerak.
qo'shib qo'ydi muallif John Bode, manba

Markerning kattaligi u ko'rsatayotgan ma'lumot turiga qat'i nazar, bir xil bo'ladi.

may turli xil darajada va vakillikka ega bo'lishi kerak, bu albatta ko'rsatma emas:

void uchun ko'rsatgich bir xil vakillik va hizalama talablariga ega bo'lishi kerak belgilarning bir turiga o'xshash. 48) Xuddi shunday, malakali yoki malakasiz versiyalarga mos keladigan turlar bir xil vakillik va moslashtirish talablariga ega bo'lishi kerak. Hammasi struktura tipidagi ko'rsatgichlar bir xil vakillik va moslashtirish talablariga ega bo'lishi kerak bir-birlari kabi. Ittifoq turlarining barcha ko'rsatgichlari bir xil vakillikka ega bo'lishi kerak moslashuvchanlik talablari bir-birlari kabi. Boshqa turdagi ko'rsatgichlar bir xil bo'lmasligi kerak vakillik yoki hizalama talablari .

C 2011 Online Draft, §6.2.5 ¶28

Pointer tiplarining qiymatini ko'rsatish amalga oshiriladigan dastur hisoblanadi. Joylashuv mos keladigan turdagi ko'rsatkichlar bir xil qiymatga ega bo'lishi kerak va hizalama talablari (3.11).

C++ 2014 Working Draft, §3.9.2, ¶3

Ko'pgina zamonaviy stol va serverlarda ular bir xil, lekin umuman olganda haqiqat bo'lishini kutishmaydi.

Shunda nima uchun biz ko'rsatadigan ma'lumot turini e'lon qilishimiz kerak?

Pointer arifmetikasi T turidagi ob'ektga p belgisi ishora qilingan turiga bog'liq, keyin p + 1 keyingi obyektga ishora qiladi T turiga kiring. Turli xil o'lchamlarga ega bo'lganligi sababli, to`g`ri to`g`ri to`g`ri to`g`ri to`g`ri to`g`ri bilishingiz kerak.

1
qo'shib qo'ydi

So'ngra, nega bu kabi ko'rsatgich deklaratsiyasini umumlashtira olmaymiz

 pointer p;//bu erda p - ko'rsatgich sinfining ob'ektidir.
 
-ni tanlang

Siz aslida void * dan foydalanishingiz mumkin. Lekin natijasi shundaki, barcha turdagi (va hajmi bo'yicha) ma'lumotlar shu nuqtada yo'qoladi.

Buni foydali qilish uchun siz qandaydir tarzda (hard-kodli turdagi yoki boshqa narsalarni) kuzatib borishingiz kerak.

0
qo'shib qo'ydi
C yoki C ++ dan boshqa (gipotetik) til boshqa ma'lumotni " pointer" bilan "/" bilan "qandaydir tarzda" bo'lishi mumkin.
qo'shib qo'ydi muallif Ðаn, manba
Haqiqat ... Men "ishlaydigan" ba'zi bir "oqilona" ta'rif uchun C ++ da ishlaydigan "code> pointer"
qo'shib qo'ydi muallif Ðаn, manba
Buning uchun biz hatto hypothetica tiliga ehtiyoj sezmaysiz. Barcha markerni aniq operatorlar bekor qilishi mumkin. aqlli ko'rsatkichlar ga qarang.
qo'shib qo'ydi muallif πάντα ῥεῖ, manba