C belgilarini belgilash qoidalari qanday?

K&R doesn't go over it, but they use it. I tried seeing how it'd work by writing an example program, but it didn't go so well:

#include  
int bleh (int *); 

int main(){
    char c = '5'; 
    char *d = &c;

    bleh((int *)d); 
    return 0;  
}

int bleh(int *n){
    printf("%d bleh\n", *n); 
    return *n; 
}

Bu kompilyatsiya qiladi, lekin mening bosim bayonotim axlat o'zgaruvchilari (ular dasturni har safar chaqirganimda farq qiladi). Har qanday fikr bormi?

52
'5' - bu raqam int kabi ko'rinadi, chunki u raqam sifatida ko'rinadi, ammo bu faqat raqamni ifodalovchi belgidir.
qo'shib qo'ydi muallif mah, manba
'5' - bu raqam int kabi ko'rinadi, chunki u raqam sifatida ko'rinadi, ammo bu faqat raqamni ifodalovchi belgidir.
qo'shib qo'ydi muallif mah, manba
* n qiymati 4 bayta bo'lishi kerak bo'lgan int bo'ladi. * n , main() c mahalliy o'zgaruvchiga ishora qiladi. Ya'ni 'c' qiymatini yozib qo'yasiz va qaysi uchta bayt uni xotirada saqlaydi. (Mening taxminimcha, d qiymatidir.) Buni oltitadan yozib tasdiqlashingiz mumkin - ikkala raqam har safar bir xil bo'lishi kerak.
qo'shib qo'ydi muallif millimoose, manba
* n qiymati 4 bayta bo'lishi kerak bo'lgan int bo'ladi. * n , main() c mahalliy o'zgaruvchiga ishora qiladi. Ya'ni 'c' qiymatini yozib qo'yasiz va qaysi uchta bayt uni xotirada saqlaydi. (Mening taxminimcha, d qiymatidir.) Buni oltitadan yozib tasdiqlashingiz mumkin - ikkala raqam har safar bir xil bo'lishi kerak.
qo'shib qo'ydi muallif millimoose, manba
int, chardan kattaroq hajmga ega, shuning uchun u "5" chizig'idan tashqarida o'qish. Kichik ma'lumot turini (int c, printf "% c") ishlatib, xuddi shu narsani bajaring.
qo'shib qo'ydi muallif SheetJS, manba
Mashinamda xuddi shu testni qildim (gcc, x86_64) va hech qanday kompilyatsiya xatolikka yo'l qo'ymadim va dastur har safar yaxshi ishlamoqda (hech qanday axlat). Lekin o'shandan boshqa hech narsa qilmadim. Ajoyib.
qo'shib qo'ydi muallif Andy J, manba
Mashinamda xuddi shu testni qildim (gcc, x86_64) va hech qanday kompilyatsiya xatolikka yo'l qo'ymadim va dastur har safar yaxshi ishlamoqda (hech qanday axlat). Lekin o'shandan boshqa hech narsa qilmadim. Ajoyib.
qo'shib qo'ydi muallif Andy J, manba
Ushbu javobni o'qigan har bir kishi R.ning quyidagi javobni ko'rib chiqishi kerak
qo'shib qo'ydi muallif polynomial_donut, manba

12 javoblar

Ko'rsatkichlar haqida o'ylashganda, diagramlarni chizish ga yordam beradi. Pointer - qiymat turini bildiruvchi yorliq bilan xotirada manzilni ko'rsatadigan o'q. Unvon qaerga qarashini ko'rsatadi va turini olish kerakligini bildiradi. Markerni tirgaklash yorliqni o'qda o'zgartiradi, ammo o'qning belgilarini aks ettirmaydi.

d in main is a pointer to c which is of type char. A char is one byte of memory, so when d is dereferenced, you get the value in that one byte of memory. In the diagram below, each cell represents one byte.

-+----+----+----+----+----+----+-
 |    | c  |    |    |    |    | 
-+----+----+----+----+----+----+-
       ^~~~
       | char
       d

Siz d kodini d -ga yozganingizda d , albatta, int qiymatiga ishora qilyapsiz. Bugungi kunda ko'pgina tizimlarda int 4 baytni egallaydi.

-+----+----+----+----+----+----+-
 |    | c  | ?₁ | ?₂ | ?₃ |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       (int*)d

Sizda (int *) d parametrini o'zgartirsangiz, bu to'rtta bayt xotiradan belgilangan qiymatni olasiz. Siz olgan qiymat ? belgilanadigan bu kameralardagi narsalarga va int xotirada qanday namoyon etilganiga bog'liq.

Agar kompyuter kam sonli bo'lsa, bu int ning qiymati bu tarzda hisoblangan degan ma'noni anglatadi (u 4 baytni tashkil qiladi): * ((int *) d) == c + ₁ * 2⁸ + ₂ * 2¹⁶ + ₃ * 2²⁴ . Agar qiymatni o'n oltinchi ( printf ("% x \ n", * n) ) ichida yozsangiz, oxirgi ikki raqam har doim 35 (bu '5' belgi qiymati).

Boshqa ba'zi tizimlar juda katta va boshqa yo'nalishdagi baytlarni tashkil qiladi: * ((int *) d) == c * 2²⁴ +? ₁ * 2¹⁶ + ₂ + 2⁸ + ₃ . Ushbu tizimlarda o'n oltilikda chop etilgan qiymat har doim boshlanadi 35 bilan ishlaydi. Ba'zi tizimlarda 4 bayttan farqli int hajmi bor. Nodir bir nechta tizim int ni turli yo'llar bilan tashkil qiladi, lekin siz ularni duch kelishi mumkin emas.

Derivatoringiz va operatsion tizimingizga bog'liq holda, dasturni ishga tushirganingizda qiymati har xil bo'lsa yoki u har doim bir xil bo'lsa-da, lekin manba kodiga kichik tweaks ni o'zgartirganda o'zgaradi.

Ba'zi tizimlarda int qiymati 4 (yoki 2 yoki 8) ning ko'prigi bo'lgan manzilda saqlanishi kerak. Bunga moslashtirish talab etiladi. c manzilining to'g'ri muvofiqlashtirilganligi yoki mavjud emasligiga qarab, dastur qulashi mumkin.

Dasturingizdan farqli o'laroq, bu erda int qiymatiga ega bo'lganingizda va u uchun markerni olib borishda nima sodir bo'ladi.

int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
 |    |         x         |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       p

Pointer P bir int qiymatiga ishora qiladi. Okdagi yorliq xotira xujayrasidagi narsalarni aniq tasvirlaydi, shuning uchun uni ajratib olishda kutilmagan hodisalar yo'q.

96
qo'shib qo'ydi
"... oxirgi ikki raqam har doim 35 bo'ladi (5 belgining qiymati shu)." Nima uchun?
qo'shib qo'ydi muallif Kenneth Worden, manba
@SummerSun Nima uchun bu 61626364 bo'lishi kerak deb o'ylaysiz? Agar sizda endian kompyuteringiz bor bo'lsa (barcha kompyuterlar juda kichik), bu 64636261 bo'ladi. Bu xotiraning o'qilishi tartibiga hech qanday aloqasi yo'q. int , ehtimol bitta buyruqda o'qiladi. Bu 4 bayt bloki int qiymati sifatida qanday talqin qilinishi haqida.
qo'shib qo'ydi muallif Gilles, manba
Yaxshi tushuntirish. Shuni ta'kidlashni istardimki, aksariyat kompyuterlarda int 32-bitlik qiymatga ega bo'lishi mumkin, ammo boshqa integratsiya muhandislar uchun int odatda 16-bit va u qanchalik foydali ekanligini ko'rsatadi va, ehtimol, uint16_t, uint32_t, int32_t va hokazolardan foydalanish juda muhim bo'lishi mumkin va hokazo. Aqlli eshak bo'lishga urinmaslik kerak, xafa qilmang. :)
qo'shib qo'ydi muallif DiBosco, manba
Xristian Gilles, kodni sinab ko'rganimda bu erda char * a = "abcd"; int * i = (int *) a; printf ("% x \ n", * i); chiqish 64636261 ni tashkil qiladi, ammo u 61626364 bo'lishi kerak deb o'ylayman. Bu ushbu blokning ichidagi xotira oldindan oldindan o'qilganligini anglatadimi?
qo'shib qo'ydi muallif Summer Sun, manba
Rahmat @Gilles Men ma'lumot turi xotira buyurtma bo'yicha buyurtma deb o'yladim, men hozir juda oz endian uchun tushunaman, bir nechta baytni o'z ichiga olgan ma'lumot turining qiymati pastdan yuqoriga qadar yopilgan.
qo'shib qo'ydi muallif Summer Sun, manba

Ko'rsatkichlar haqida o'ylashganda, diagramlarni chizish ga yordam beradi. Pointer - qiymat turini bildiruvchi yorliq bilan xotirada manzilni ko'rsatadigan o'q. Unvon qaerga qarashini ko'rsatadi va turini olish kerakligini bildiradi. Markerni tirgaklash yorliqni o'qda o'zgartiradi, ammo o'qning belgilarini aks ettirmaydi.

d in main is a pointer to c which is of type char. A char is one byte of memory, so when d is dereferenced, you get the value in that one byte of memory. In the diagram below, each cell represents one byte.

-+----+----+----+----+----+----+-
 |    | c  |    |    |    |    | 
-+----+----+----+----+----+----+-
       ^~~~
       | char
       d

Siz d kodini d -ga yozganingizda d , albatta, int qiymatiga ishora qilyapsiz. Bugungi kunda ko'pgina tizimlarda int 4 baytni egallaydi.

-+----+----+----+----+----+----+-
 |    | c  | ?₁ | ?₂ | ?₃ |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       (int*)d

Sizda (int *) d parametrini o'zgartirsangiz, bu to'rtta bayt xotiradan belgilangan qiymatni olasiz. Siz olgan qiymat ? belgilanadigan bu kameralardagi narsalarga va int xotirada qanday namoyon etilganiga bog'liq.

Agar kompyuter kam sonli bo'lsa, bu int ning qiymati bu tarzda hisoblangan degan ma'noni anglatadi (u 4 baytni tashkil qiladi): * ((int *) d) == c + ₁ * 2⁸ + ₂ * 2¹⁶ + ₃ * 2²⁴ . Agar qiymatni o'n oltinchi ( printf ("% x \ n", * n) ) ichida yozsangiz, oxirgi ikki raqam har doim 35 (bu '5' belgi qiymati).

Boshqa ba'zi tizimlar juda katta va boshqa yo'nalishdagi baytlarni tashkil qiladi: * ((int *) d) == c * 2²⁴ +? ₁ * 2¹⁶ + ₂ + 2⁸ + ₃ . Ushbu tizimlarda o'n oltilikda chop etilgan qiymat har doim boshlanadi 35 bilan ishlaydi. Ba'zi tizimlarda 4 bayttan farqli int hajmi bor. Nodir bir nechta tizim int ni turli yo'llar bilan tashkil qiladi, lekin siz ularni duch kelishi mumkin emas.

Derivatoringiz va operatsion tizimingizga bog'liq holda, dasturni ishga tushirganingizda qiymati har xil bo'lsa yoki u har doim bir xil bo'lsa-da, lekin manba kodiga kichik tweaks ni o'zgartirganda o'zgaradi.

Ba'zi tizimlarda int qiymati 4 (yoki 2 yoki 8) ning ko'prigi bo'lgan manzilda saqlanishi kerak. Bunga moslashtirish talab etiladi. c manzilining to'g'ri muvofiqlashtirilganligi yoki mavjud emasligiga qarab, dastur qulashi mumkin.

Dasturingizdan farqli o'laroq, bu erda int qiymatiga ega bo'lganingizda va u uchun markerni olib borishda nima sodir bo'ladi.

int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
 |    |         x         |    | 
-+----+----+----+----+----+----+-
       ^~~~~~~~~~~~~~~~~~~
       | int
       p

Pointer P bir int qiymatiga ishora qiladi. Okdagi yorliq xotira xujayrasidagi narsalarni aniq tasvirlaydi, shuning uchun uni ajratib olishda kutilmagan hodisalar yo'q.

96
qo'shib qo'ydi
"... oxirgi ikki raqam har doim 35 bo'ladi (5 belgining qiymati shu)." Nima uchun?
qo'shib qo'ydi muallif Kenneth Worden, manba
@SummerSun Nima uchun bu 61626364 bo'lishi kerak deb o'ylaysiz? Agar sizda endian kompyuteringiz bor bo'lsa (barcha kompyuterlar juda kichik), bu 64636261 bo'ladi. Bu xotiraning o'qilishi tartibiga hech qanday aloqasi yo'q. int , ehtimol bitta buyruqda o'qiladi. Bu 4 bayt bloki int qiymati sifatida qanday talqin qilinishi haqida.
qo'shib qo'ydi muallif Gilles, manba
Yaxshi tushuntirish. Shuni ta'kidlashni istardimki, aksariyat kompyuterlarda int 32-bitlik qiymatga ega bo'lishi mumkin, ammo boshqa integratsiya muhandislar uchun int odatda 16-bit va u qanchalik foydali ekanligini ko'rsatadi va, ehtimol, uint16_t, uint32_t, int32_t va hokazolardan foydalanish juda muhim bo'lishi mumkin va hokazo. Aqlli eshak bo'lishga urinmaslik kerak, xafa qilmang. :)
qo'shib qo'ydi muallif DiBosco, manba
Xristian Gilles, kodni sinab ko'rganimda bu erda char * a = "abcd"; int * i = (int *) a; printf ("% x \ n", * i); chiqish 64636261 ni tashkil qiladi, ammo u 61626364 bo'lishi kerak deb o'ylayman. Bu ushbu blokning ichidagi xotira oldindan oldindan o'qilganligini anglatadimi?
qo'shib qo'ydi muallif Summer Sun, manba
Rahmat @Gilles Men ma'lumot turi xotira buyurtma bo'yicha buyurtma deb o'yladim, men hozir juda oz endian uchun tushunaman, bir nechta baytni o'z ichiga olgan ma'lumot turining qiymati pastdan yuqoriga qadar yopilgan.
qo'shib qo'ydi muallif Summer Sun, manba
char c = '5'

0x12345678 manzilida char (1 bayt) stack ustida ajratilgan.

char *d = &c;

Siz c manzilini olasiz va uni d da saqlashingiz mumkin, shuning uchun d = 0x12345678 .

int *e = (int*)d;

0x12345678 kodi int ga ishora qilsa, derazadan faqat bitta bayta ( sizeof (char)! = Sizeof (int) ). Arxitektura yoki hatto boshqa qadriyatlarga muvofiq 4 yoki 8 bayt bo'lishi mumkin.

Shunday qilib, markerni qiymatini yozganda, tamsayı, birinchi bayt (ya'ni, c ) va ketma-ket bo'lgan ketma-ket baytlarni qabul qilib, niyatingiz uchun faqat axlatni hisobga olinadi.

28
qo'shib qo'ydi
d , 0x12345678 ni ushlab turadigan darajada katta emas
qo'shib qo'ydi muallif A Person, manba
@Person nima uchun bu?
qo'shib qo'ydi muallif YoYoYonnY, manba
Boshqa ketma-ket baytlar axlat emas, balki sizning namunangizda d , ya'ni 0x12345678 qiymati.
qo'shib qo'ydi muallif Kane, manba
char c = '5'

0x12345678 manzilida char (1 bayt) stack ustida ajratilgan.

char *d = &c;

Siz c manzilini olasiz va uni d da saqlashingiz mumkin, shuning uchun d = 0x12345678 .

int *e = (int*)d;

0x12345678 kodi int ga ishora qilsa, derazadan faqat bitta bayta ( sizeof (char)! = Sizeof (int) ). Arxitektura yoki hatto boshqa qadriyatlarga muvofiq 4 yoki 8 bayt bo'lishi mumkin.

Shunday qilib, markerni qiymatini yozganda, tamsayı, birinchi bayt (ya'ni, c ) va ketma-ket bo'lgan ketma-ket baytlarni qabul qilib, niyatingiz uchun faqat axlatni hisobga olinadi.

28
qo'shib qo'ydi
d , 0x12345678 ni ushlab turadigan darajada katta emas
qo'shib qo'ydi muallif A Person, manba
@Person nima uchun bu?
qo'shib qo'ydi muallif YoYoYonnY, manba
Boshqa ketma-ket baytlar axlat emas, balki sizning namunangizda d , ya'ni 0x12345678 qiymati.
qo'shib qo'ydi muallif Kane, manba

To'qimalarining ko'rsatgichlari odatda Cda haqiqiy emas. Bir necha sabablar bor:

  1. Alignment. It's possible that, due to alignment considerations, the destination pointer type is not able to represent the value of the source pointer type. For example, if int * were inherently 4-byte aligned, casting char * to int * would lose the lower bits.

  2. Aliasing. In general it's forbidden to access an object except via an lvalue of the correct type for the object. There are some exceptions, but unless you understand them very well you don't want to do it. Note that aliasing is only a problem if you actually dereference the pointer (apply the * or -> operators to it, or pass it to a function that will dereference it).

Kasting ko'rsatkichlari yaxshi bo'lgan asosiy holatlar quyidagilardir:

  1. Nishon pointer turi belgi turiga ishora qilganda. Belgilar turiga ishora qiluvchi har qanday markerni ifodalashga imkon beradigan va xohlagan taqdirda uni asl nusxada qayta ishlashga imkon beradigan kafolat beriladi. Pointer void ( void * ) belgilarga o'xshash belgilar bilan bir xil bo'ladi, bundan tashqari uni sizdan olib tashlash yoki unga arifmetik qilish huquqi berilmaydi va avtomatik ravishda boshqa markerlarga bunday tovarlarga ehtiyoj sezmaydigan turlarni kiritish kerak, shuning uchun ko'rsatgichlarni bekor qilish, odatda, bu maqsad uchun belgi turlari bo'yicha ko'rsatkichlar bo'yicha afzaldir.

  2. Nishon pointer turi qurilma turi uchun marker bo'lsa, a'zolar dastlabki nuqtada ko'rsatilgan tuzilish turiga dastlabki a'zolariga mos keladi. Bu C ob'ektida ob'ektga asoslangan turli xil dasturlash texnikasi uchun foydalidir.

Boshqa ba'zi qarama-qarshi holatlar texnik jihatdan til talablari jihatidan yaxshi, lekin muammoli va eng yaxshi yo'l tutishadi.

12
qo'shib qo'ydi
Ushbu murakkab vaziyatlarda rasmiy hujjat bilan bog'lana olasizmi?
qo'shib qo'ydi muallif Eric, manba
@EvanBenn: Ehtimol. Tampon malloc orqali olingan bo'lsa va ma'lumotlarni fread yoki shunga o'xshash tarzda saqlasangiz, u holda offsets mos keladigan (umuman, bu qiyin bo'lishi mumkin) belgilash kerak, lekin agar ular turdagi kattalikka aylangan bo'lsa, albatta) to'g'ri ko'rsatkichga aylantirilishi va bunday ma'lumotga kirish uchun mos bo'lishi kerak. Agar siz haqiqiy kod char [N] yoki nimadir bo'lgan bufer bilan ishlayotgan bo'lsangiz, u haqiqiy emas.
qo'shib qo'ydi muallif R.., manba
Bir necha joylarda kodni ko'rdim, u char * oladi va uni boshqa bir pointerga yozadi, masalan int. Masalan, kameradan oqim RGB qiymatlari yoki tarmoqdan baytlar. Malumotingiz ushbu kodning yaroqsiz ekanligini anglatadimi? Kodni to'g'rilash uchun etarli ma'lumotni moslashtiradimi yoki bizning oddiy derleyicilerimiz ushbu qo'llanilish uchun yumshoqmi?
qo'shib qo'ydi muallif Evan Benn, manba

To'qimalarining ko'rsatgichlari odatda Cda haqiqiy emas. Bir necha sabablar bor:

  1. Alignment. It's possible that, due to alignment considerations, the destination pointer type is not able to represent the value of the source pointer type. For example, if int * were inherently 4-byte aligned, casting char * to int * would lose the lower bits.

  2. Aliasing. In general it's forbidden to access an object except via an lvalue of the correct type for the object. There are some exceptions, but unless you understand them very well you don't want to do it. Note that aliasing is only a problem if you actually dereference the pointer (apply the * or -> operators to it, or pass it to a function that will dereference it).

Kasting ko'rsatkichlari yaxshi bo'lgan asosiy holatlar quyidagilardir:

  1. Nishon pointer turi belgi turiga ishora qilganda. Belgilar turiga ishora qiluvchi har qanday markerni ifodalashga imkon beradigan va xohlagan taqdirda uni asl nusxada qayta ishlashga imkon beradigan kafolat beriladi. Pointer void ( void * ) belgilarga o'xshash belgilar bilan bir xil bo'ladi, bundan tashqari uni sizdan olib tashlash yoki unga arifmetik qilish huquqi berilmaydi va avtomatik ravishda boshqa markerlarga bunday tovarlarga ehtiyoj sezmaydigan turlarni kiritish kerak, shuning uchun ko'rsatgichlarni bekor qilish, odatda, bu maqsad uchun belgi turlari bo'yicha ko'rsatkichlar bo'yicha afzaldir.

  2. Nishon pointer turi qurilma turi uchun marker bo'lsa, a'zolar dastlabki nuqtada ko'rsatilgan tuzilish turiga dastlabki a'zolariga mos keladi. Bu C ob'ektida ob'ektga asoslangan turli xil dasturlash texnikasi uchun foydalidir.

Boshqa ba'zi qarama-qarshi holatlar texnik jihatdan til talablari jihatidan yaxshi, lekin muammoli va eng yaxshi yo'l tutishadi.

12
qo'shib qo'ydi
Ushbu murakkab vaziyatlarda rasmiy hujjat bilan bog'lana olasizmi?
qo'shib qo'ydi muallif Eric, manba
@EvanBenn: Ehtimol. Tampon malloc orqali olingan bo'lsa va ma'lumotlarni fread yoki shunga o'xshash tarzda saqlasangiz, u holda offsets mos keladigan (umuman, bu qiyin bo'lishi mumkin) belgilash kerak, lekin agar ular turdagi kattalikka aylangan bo'lsa, albatta) to'g'ri ko'rsatkichga aylantirilishi va bunday ma'lumotga kirish uchun mos bo'lishi kerak. Agar siz haqiqiy kod char [N] yoki nimadir bo'lgan bufer bilan ishlayotgan bo'lsangiz, u haqiqiy emas.
qo'shib qo'ydi muallif R.., manba
Bir necha joylarda kodni ko'rdim, u char * oladi va uni boshqa bir pointerga yozadi, masalan int. Masalan, kameradan oqim RGB qiymatlari yoki tarmoqdan baytlar. Malumotingiz ushbu kodning yaroqsiz ekanligini anglatadimi? Kodni to'g'rilash uchun etarli ma'lumotni moslashtiradimi yoki bizning oddiy derleyicilerimiz ushbu qo'llanilish uchun yumshoqmi?
qo'shib qo'ydi muallif Evan Benn, manba

Yana bir umumiy javob kerak, deb o'ylayman:

C belgilarini belgilashda qoidalar yo'q! Til siz sharh bermasdan biron-bir boshqa markerga biron-bir markerni suratga olish imkonini beradi.

Lekin bu narsa: Ma'lumotni konvertatsiya qilish yoki bajarilmasin! U faqatgina o'zingizning javobgarligingiz, tizim tizimdan so'ng ma'lumotlarni noto'g'ri talqin qilmaydi - bu odatda ish vaqti xatosiga olib keladi.

Xullas, agar siz ma'lumotlar to'qimalangan ko'rsatgichdan foydalansangiz, ma'lumotlar mos keladi!

C ishlash uchun optimallashtirildi, shuning uchun ishora ishoralarining refleksivligi yo'q. Lekin, bu narxi bor - dasturchi sifatida nima qilayotganingizni yaxshi bilishingiz kerak. Siz o'zingizni bilishingiz kerak bo'lsa, nima qilishni istasangiz, "qonuniy"

2
qo'shib qo'ydi
Kvalifikatsiya ko'rsatgichlari haqida qoidalar mavjud, ularning bir qismi C 2011 standartidagi 6.3.2.3-bandda keltirilgan. Boshqa narsalar bilan bir qatorda, narsalarga ko'rsatgichlar boshqa moslamalarni ob'ektlarga surish mumkin va agar aylantirilsa, originalga teng taqqoslanadi. Funksiyalarga ishora qiluvchi ko'rsatgichlar boshqa funktsiyalarga funksiyalarga o'tkazilishi mumkin va agar aylantirilsa, teng ravishda taqqoslanadi. Ko'rsatkichlarni funktsiyalarga ko'rsatadigan ko'rsatgichlarga moslamalarni o'zgartirmaslik, aniqlanmagan xatti-harakatlarga olib keladi. Ob'ektlarga ishora qiluvchi belgilarga markerlarga aylantirilishi va ob'ektning baytlariga kirish uchun ishlatilishi mumkin.
qo'shib qo'ydi muallif Eric Postpischil, manba
@aqjune Siz C deb nomlanadigan mashhur kengaytmani sarlavhasi qilyapsiz. Bu faqat standart emas.
qo'shib qo'ydi muallif pipe, manba
Ko'rsatkichlarni vazifalarga ko'rsatgichlarga moslamalarga aylantirishga ruxsat beriladi. "Agar funktsiyani ko'rsatadigan belgi ob'ektga ob'ektni ko'rsatgichga yoki bekor qilinsa, funktsiyaning tekshirilishi yoki o'zgartirilishi (masalan, tuzatuvchi tomonidan) bo'lishi mumkin", J.5.7
qo'shib qo'ydi muallif aqjune, manba

Yana bir umumiy javob kerak, deb o'ylayman:

C belgilarini belgilashda qoidalar yo'q! Til siz sharh bermasdan biron-bir boshqa markerga biron-bir markerni suratga olish imkonini beradi.

Lekin bu narsa: Ma'lumotni konvertatsiya qilish yoki bajarilmasin! U faqatgina o'zingizning javobgarligingiz, tizim tizimdan so'ng ma'lumotlarni noto'g'ri talqin qilmaydi - bu odatda ish vaqti xatosiga olib keladi.

Xullas, agar siz ma'lumotlar to'qimalangan ko'rsatgichdan foydalansangiz, ma'lumotlar mos keladi!

C ishlash uchun optimallashtirildi, shuning uchun ishora ishoralarining refleksivligi yo'q. Lekin, bu narxi bor - dasturchi sifatida nima qilayotganingizni yaxshi bilishingiz kerak. Siz o'zingizni bilishingiz kerak bo'lsa, nima qilishni istasangiz, "qonuniy"

2
qo'shib qo'ydi
Kvalifikatsiya ko'rsatgichlari haqida qoidalar mavjud, ularning bir qismi C 2011 standartidagi 6.3.2.3-bandda keltirilgan. Boshqa narsalar bilan bir qatorda, narsalarga ko'rsatgichlar boshqa moslamalarni ob'ektlarga surish mumkin va agar aylantirilsa, originalga teng taqqoslanadi. Funksiyalarga ishora qiluvchi ko'rsatgichlar boshqa funktsiyalarga funksiyalarga o'tkazilishi mumkin va agar aylantirilsa, teng ravishda taqqoslanadi. Ko'rsatkichlarni funktsiyalarga ko'rsatadigan ko'rsatgichlarga moslamalarni o'zgartirmaslik, aniqlanmagan xatti-harakatlarga olib keladi. Ob'ektlarga ishora qiluvchi belgilarga markerlarga aylantirilishi va ob'ektning baytlariga kirish uchun ishlatilishi mumkin.
qo'shib qo'ydi muallif Eric Postpischil, manba
@aqjune Siz C deb nomlanadigan mashhur kengaytmani sarlavhasi qilyapsiz. Bu faqat standart emas.
qo'shib qo'ydi muallif pipe, manba
Ko'rsatkichlarni vazifalarga ko'rsatgichlarga moslamalarga aylantirishga ruxsat beriladi. "Agar funktsiyani ko'rsatadigan belgi ob'ektga ob'ektni ko'rsatgichga yoki bekor qilinsa, funktsiyaning tekshirilishi yoki o'zgartirilishi (masalan, tuzatuvchi tomonidan) bo'lishi mumkin", J.5.7
qo'shib qo'ydi muallif aqjune, manba

Sizda char uchun marker bor. Shunday qilib, tizimingiz biladiki, u xotira manzilida sizeof (char) maydonida char qiymati mavjud. Uni int * -ga chiqarganingizda, sizeof (int) ma'lumoti bilan ishlaysiz, shuning uchun siz char va ba'zi bir xotira axlatlarini bir tamsaydan keyin .

2
qo'shib qo'ydi

Sizda char uchun marker bor. Shunday qilib, tizimingiz biladiki, u xotira manzilida sizeof (char) maydonida char qiymati mavjud. Uni int * -ga chiqarganingizda, sizeof (int) ma'lumoti bilan ishlaysiz, shuning uchun siz char va ba'zi bir xotira axlatlarini bir tamsaydan keyin .

2
qo'shib qo'ydi

Axlat qiymati, aslida funktsiyani bleh() ni e'lon qilishdan avval deb ataganligi sababli bo'ladi.

In case of C++ you will get compilation error but in c, the compiler assumes that the return type of the function is int, whereas, your function is returning a pointer to integer.

See this for more info : http://www.geeksforgeeks.org/g-fact-95/

2
qo'shib qo'ydi
Funktsiya chaqiruvdan oldin e'lon qilinadi.
qo'shib qo'ydi muallif ad3angel1s, manba

Axlat qiymati, aslida funktsiyani bleh() ni e'lon qilishdan avval deb ataganligi sababli bo'ladi.

In case of C++ you will get compilation error but in c, the compiler assumes that the return type of the function is int, whereas, your function is returning a pointer to integer.

See this for more info : http://www.geeksforgeeks.org/g-fact-95/

2
qo'shib qo'ydi
Funktsiya chaqiruvdan oldin e'lon qilinadi.
qo'shib qo'ydi muallif ad3angel1s, manba