අරා සමඟ, [5] == 5 [a] සිදුවන්නේ ඇයි?


1627

සී ක්‍රමලේඛන භාෂාවෙන් (aka: K & R), ජොයෙල් ස්ටැක් ඕවර්ෆ්ලෝ පොඩ්කාස්ට් # 34 හි පෙන්වා ඇති පරිදි, සී හි අරා වල මෙම දේපල ගැන සඳහනක් ඇත:a[5] == 5[a]

ජොයෙල් පවසන්නේ එය දර්ශක අංක ගණිතය නිසා නමුත් මට තවමත් තේරෙන්නේ නැති බවයි. ඇයිa[5] == 5[a] ?


49
[+] වැනි දෙයක් * (a ++) හෝ * (++ a) මෙන් ක්‍රියා කරයිද?
එගොන්

45
Gon එගොන්: එය ඉතා නිර්මාණශීලී නමුත් අවාසනාවකට එය සම්පාදකයින් ක්‍රියා කරන්නේ කෙසේද යන්න නොවේ. සම්පාදකයා අර්ථ දක්වන්නේ a[1]ටෝකන මාලාවක් මිස නූල් නොවේ: * ({a {ක්‍රියාකරු} + {නිඛිල} 1 හි පූර්ණ සංඛ්‍යා පිහිටීම) * ({පූර්ණ සංඛ්‍යා} 1 {ක්‍රියාකරු} + {පූර්ණ සංඛ්‍යා පිහිටීම} a) නමුත් * ({a {ක්‍රියාකරු} + {ක්‍රියාකරු} + හි පූර්ණ සංඛ්‍යා පිහිටීම) ට සමාන නොවේ
දීනා

11
මේ පිළිබඳ සිත්ගන්නාසුලු සංයෝග විචල්‍යතාවයක් ඉලොජිකල් අරා ප්‍රවේශය තුළ විදහා දක්වයි , එහිදී ඔබ සතුව ඇති char bar[]; int foo[];අතර foo[i][bar]එය ප්‍රකාශනයක් ලෙස භාවිතා කරයි.
ජොනතන් ලෙෆ්ලර්

5
එල්ඩ්රිච්කොන්ඩ්‍රම්, 'සම්පාදකයාට වම් කොටස දර්ශකයක් දැයි පරීක්ෂා කළ නොහැක' කියා ඔබ සිතන්නේ ඇයි? ඔව්, එයට හැකිය. a[b]= *(a + b)ඕනෑම දෙයකට aසහ b, නමුත් එය +සියලු වර්ගවල සංක්‍රමණික ලෙස අර්ථ දැක්වීම සඳහා භාෂා නිර්මාණකරුවන්ගේ නිදහස් තේරීම බව සත්‍යයකි . i + pඉඩ දෙන අතරතුර ඒවා තහනම් කිරීමෙන් වළක්වා ගත හැකි කිසිවක් නැත p + i.
ach

13
Nd ඇන්ඩ්‍රි වන් සාමාන්‍යයෙන් අපේක්‍ෂා කරන්නේ සංක්‍රමණික වීමටය +, එබැවින් සැබෑ ගැටළුව වන්නේ වෙනම ඕෆ්සෙට් ක්‍රියාකරුවෙකු සැලසුම් කිරීම වෙනුවට දර්ශක මෙහෙයුම් ගණිතයට සමාන කිරීමට තෝරා ගැනීමයි.
එල්ඩ්‍රිච් කොන්ඩ්‍රම්

Answers:


1930

සී ප්‍රමිතිය මඟින් []ක්‍රියාකරු පහත පරිදි අර්ථ දක්වයි :

a[b] == *(a + b)

එබැවින් පහත a[5]පරිදි ඇගයීමට ලක් කෙරේ:

*(a + 5)

සහ 5[a]ඇගයීමට ලක් කරන්නේ:

*(5 + a)

aයනු අරාවෙහි පළමු අංගයට දර්ශකයකි. මූලද්‍රව්‍යa[5] 5 ක් තව දුරටත් ඇති අගය , එය සමාන වන අතර ප්‍රාථමික පාසල් ගණිතයෙන් ඒවා සමාන බව අපි දනිමු (එකතු කිරීම සංක්‍රමණික වේ ).a*(a + 5)


325
එය * ((5 * ප්‍රමාණයෙන් (අ)) + අ) වඩා වැඩි නොවේදැයි මට සිතේ. විශිෂ්ට පැහැදිලි කිරීමක් වුවද.
ජෝන් මැකින්ටයර්

92
Ina ඩිනා: සී-සම්පාදක දෘෂ්ටි කෝණයකින්, ඔබ හරි. විශාල ප්‍රමාණයක් අවශ්‍ය නොවන අතර මා සඳහන් කළ ප්‍රකාශයන් එකම වේ. කෙසේ වෙතත්, යන්ත්‍ර කේතය නිපදවීමේදී සම්පාදකයා ප්‍රමාණය සැලකිල්ලට ගනී. A යනු අරා අරා නම්, a[5]mov eax, [ebx+20]වෙනුවට වෙනත් දෙයකට සම්පාදනය කරනු ඇත[ebx+5]
මෙහර්දාඩ් අෆ්ෂාරි

13
Ina ඩිනා: A යනු ලිපිනයකි, 0x1230 කියන්න. A 32-bit int array හි නම්, [0] 0x1230, a [1] 0x1234, a [2] 0x1238 ... a [5] x1244 යනාදිය වේ. අපි 5 ට එකතු කළහොත් 0x1230, අපට 0x1235 ලැබෙනවා, එය වැරදියි.
ජේම්ස් කුරන්

37
@ sr105: එය + ක්‍රියාකරු සඳහා විශේෂ අවස්ථාවකි, එහිදී එක් ඔපෙරන්ඩ් එකක් දර්ශකයක් වන අතර අනෙක පූර්ණ සංඛ්‍යාවක් වේ. ප්‍රමිතිය පවසන්නේ ප්‍රති result ලය දර්ශකයේ වර්ගය වනු ඇති බවයි. සම්පාදකයා / ප්‍රමාණවත් විය යුතුය.
aib

49
"ප්‍රාථමික පාසල් ගණිතයේ සිට ඒවා සමාන බව අපි දනිමු" - ඔබ සරල කරන බව මට වැටහී ඇත, නමුත් මම සරල කිරීම ඉක්මවා යන බවක් හැඟෙන අය සමඟ සිටිමි . එය මූලික නොවේ *(10 + (int *)13) != *((int *)10 + 13). වෙනත් වචන වලින් කිවහොත්, ප්‍රාථමික පාසල් අංක ගණිතයට වඩා මෙහි බොහෝ දේ සිදුවෙමින් පවතී. කොමියුටේටිව් යනු සම්පාදකයා මත රඳා පවතින්නේ කුමන ක්‍රියාකාරීත්වය දර්ශකයක්ද යන්න හඳුනා ගැනීම (සහ වස්තුවේ ප්‍රමාණයට). වෙනත් ආකාරයකින් කිවහොත් (1 apple + 2 oranges) = (2 oranges + 1 apple), නමුත් (1 apple + 2 oranges) != (1 orange + 2 apples).
LarsH

287

අරාව ප්‍රවේශය අර්ථ දක්වන්නේ දර්ශකයන් අනුව ය. a[i]අර්ථ දැක්වීමට අර්ථ දක්වා ඇති *(a + i)අතර එය සංක්‍රමණික වේ.


42
අරා දර්ශකයන් අනුව අර්ථ දක්වා නැත, නමුත් ඒවාට ප්‍රවේශය වේ.
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

5
මම එකතු කරමි "එබැවින් එය සමාන වේ *(i + a), එය ලිවිය හැකිය i[a]".
ජිම් බෝල්ටර්

4
සම්මතයෙන් උපුටා දැක්වීම පහත පරිදි ඇතුළත් කිරීමට මම යෝජනා කරමි: 6.5.2.1: 2 පෝස්ට්ෆික්ස් ප්‍රකාශනයකින් පසුව හතරැස් වරහන් වල ප්‍රකාශනයක් [] යනු අරාව වස්තුවක මූලද්‍රව්‍යයක දායකත්ව නාමකරණයකි. ග්‍රාහක ක්‍රියාකරුගේ අර්ථ දැක්වීම නම් E1 [E2] (* ((E1) + (E2)) ට සමාන බවයි. ද්විමය + ක්‍රියාකරුට අදාළ වන පරිවර්තන නීති නිසා, E1 අරාව වස්තුවක් නම් (ඒ හා සමානව, අරාව වස්තුවක ආරම්භක මූලද්‍රව්‍යයට දර්ශකයක්) සහ E2 පූර්ණ සංඛ්‍යාවක් නම්, E1 [E2] E2-th මූලද්‍රව්‍යය නියම කරයි E1 (බිංදුවෙන් ගණන් කිරීම).
වලංගුභාවය

වඩාත් නිවැරදි වීමට: ඔබ ඒවාට ප්‍රවේශ වන විට අරා දර්ශකයන්ට දිරාපත් වේ.
12431234123412341234123

නිට්පික්: “ *(a + i)සංක්‍රමණිකයි” යැයි කීම තේරුමක් නැත . කෙසේ වෙතත්, එකතු කිරීම සංක්‍රමණික *(a + i) = *(i + a) = i[a]බැවින් .
ඇන්ඩ්‍රියාස් රෙජ්බ්‍රෑන්ඩ්

232

මම හිතන්නේ අනෙක් පිළිතුරු වලින් යමක් මග හැරී ඇත.

ඔව්, p[i]අර්ථ දැක්වීම අනුව සමාන වේ *(p+i), (එකතු කිරීම සංක්‍රමණශීලී බැවින්) සමාන *(i+p)වන අතර (නැවතත්, []ක්‍රියාකරුගේ අර්ථ දැක්වීම අනුව ) සමාන වේ i[p].

(සහ දී array[i], අරාවෙහි නම ව්‍යංගයෙන් අරාවේ පළමු අංගයට දර්ශකයක් බවට පරිවර්තනය වේ.)

නමුත් එකතු කිරීමේ සංක්‍රමණශීලීත්වය මේ අවස්ථාවේ දී එතරම් පැහැදිලි නැත.

ඔපෙරන්ඩ් දෙකම එකම වර්ගයට අයත් වන විට හෝ පොදු වර්ගයකට උසස් කරන ලද විවිධ සංඛ්‍යාත්මක වර්ගවල පවා, සංක්‍රමණිකතාව පරිපූර්ණ අර්ථයක් ලබා දෙයි : x + y == y + x.

නමුත් මේ අවස්ථාවේ දී අපි විශේෂයෙන් කතා කරන්නේ දර්ශක අංක ගණිතය ගැන ය, එහිදී එක් ඔපෙරන්ඩ් එකක් දර්ශකයක් වන අතර අනෙක පූර්ණ සංඛ්‍යාවක් වේ. (පූර්ණ සංඛ්‍යා + නිඛිලය වෙනස් මෙහෙයුමක් වන අතර, දර්ශකය + දර්ශකය විකාරයකි.)

සී ප්‍රමිතියේ +ක්‍රියාකරු පිළිබඳ විස්තරය ( N1570 6.5.6) මෙසේ පවසයි:

මීට අමතරව, එක්කෝ ඔපෙරන්ඩ් දෙකටම අංක ගණිතමය වර්ගයක් තිබිය යුතුය, නැතහොත් එක් ඔපෙරන්ඩ් එකක් සම්පූර්ණ වස්තු වර්ගයක් සඳහා දර්ශකයක් විය යුතු අතර අනෙක පූර්ණ සංඛ්‍යා වර්ගය තිබිය යුතුය.

එය පහසුවෙන් පැවසිය හැකිය:

මීට අමතරව, එක්කෝ ඔපෙරන්ඩ් දෙකටම අංක ගණිතමය වර්ගයක් තිබිය යුතුය, නැතහොත් වම් ඔපෙරන්ඩ් එක සම්පූර්ණ වස්තු වර්ගයක් සඳහා දර්ශකයක් විය යුතු අතර දකුණු ඔපෙරන්ඩ්හි පූර්ණ සංඛ්‍යා වර්ගය තිබිය යුතුය.

එම අවස්ථා දෙකෙහිම i + pසහ i[p]නීති විරෝධී වනු ඇත.

C ++ පදයට අනුව, අපට ඇත්ත වශයෙන්ම අධි බර පැටවූ +ක්‍රියාකරුවන් කට්ටල දෙකක් ඇත , ඒවා ලිහිල් ලෙස විස්තර කළ හැකිය:

pointer operator+(pointer p, integer i);

සහ

pointer operator+(integer i, pointer p);

ඒවායින් පළමුවැන්න පමණක් අවශ්‍ය වේ.

ඉතින් ඇයි මේ වගේ?

C ++ ට මෙම අර්ථ දැක්වීම C වෙතින් උරුම වූ අතර එය B වෙතින් ලබා ගන්නා ලදි (අරාව සුචිගත කිරීමේ සංක්‍රමණිකතාව 1972 පරිශීලකයින්ගේ B හි සඳහන් කර ඇත ), එය BCPL (1967 දිනැති අත්පොත) වෙතින් ලබා ගත් අතර එය බොහෝ විට එය පවා ලබාගෙන ඇත. පෙර භාෂා (සීපීඑල්? ඇල්ගොල්?).

එබැවින් අරාව සුචිගත කිරීම අර්ථ දැක්වෙන්නේ එකතු කිරීම අනුව වන අතර, එම එකතු කිරීම, දර්ශකයක් සහ පූර්ණ සංඛ්‍යාවක් පවා සංක්‍රමණික වේ යන අදහස දශක ගණනාවකට පෙර සී හි මුතුන් මිත්තන්ගේ භාෂාවලට දිව යයි.

එම භාෂාවන් නූතන සී වලට වඩා තදින් ටයිප් කර ඇත. විශේෂයෙන්, දර්ශක සහ නිඛිල අතර වෙනස බොහෝ විට නොසලකා හරින ලදි. (මුල් සී ක්‍රමලේඛකයින් සමහර විට unsignedභාෂාවට මූලික පදය එක් කිරීමට පෙර අත්සන් නොකළ පූර්ණ සංඛ්‍යා ලෙස දර්ශක භාවිතා කළහ.) එබැවින් ඔපෙරන්ඩ්ස් විවිධ වර්ගවල බැවින් එකතු කිරීම සංක්‍රමණ නොවන බවට පත් කිරීමේ අදහස බොහෝ විට එම භාෂාවල නිර්මාණකරුවන්ට සිදු නොවනු ඇත. පරිශීලකයෙකුට "දේවල්" දෙකක් එකතු කිරීමට අවශ්‍ය නම්, එම "දේවල්" පූර්ණ සංඛ්‍යා, දර්ශක හෝ වෙනත් යමක් වේවා, එය වැළැක්වීම භාෂාවට අදාළ නොවේ.

වසර ගණනාවක් පුරා, එම රීතියේ යම් වෙනසක් සිදුවුවහොත් පවත්නා කේතය බිඳී යනු ඇත (1989 ANSI C ප්‍රමිතිය හොඳ අවස්ථාවක් විය හැකි වුවද).

C සහ / හෝ C ++ වෙනස් කිරීම මඟින් දර්ශකය වම් පසින් තැබීම සහ දකුණු පස ඇති නිඛිලය දැනට පවතින කේත කිහිපයක් බිඳ දැමිය හැකි නමුත් සැබෑ ප්‍රකාශන බලය නැති නොවේ.

ඒ නිසා අපට දැන් arr[3]හා 3[arr]හරියටම තේරුම එකම දෙයක්, අග ආකාරයක බාහිර කවදාවත් පෙනී යුතු වුවත් IOCCC .


12
මෙම දේපල පිළිබඳ අපූරු විස්තරය. ඉහළ මට්ටමේ දෘෂ්ටි කෝණයකින්, මම සිතන්නේ 3[arr]සිත්ගන්නාසුලු කෞතුක වස්තුවක් වන නමුත් එය කලාතුරකින් භාවිතා කළ යුතු ය. මඳ වේලාවකට පෙර මා ඇසූ මෙම ප්‍රශ්නයට (< stackoverflow.com/q/1390365/356> ) පිළිගත් පිළිතුර සින්ටැක්ස් ගැන මා සිතූ ආකාරය වෙනස් කර ඇත. බොහෝ විට තාක්ෂණික වශයෙන් මේවා කිරීමට නිවැරදි හා වැරදි ක්‍රමයක් නොතිබුණද, මේ ආකාරයේ විශේෂාංග මඟින් ඔබ සිතීමට පටන් ගන්නේ ක්‍රියාත්මක කිරීමේ තොරතුරු වලින් වෙන්වය. ක්‍රියාත්මක කිරීමේ තොරතුරු ඔබ විසින් සවි කරන විට අර්ධ වශයෙන් අහිමි වන මෙම වෙනස් චින්තනයට ප්‍රතිලාභ ඇත.
දීනා

3
එකතු කිරීම සංක්‍රමණික වේ. සී ප්‍රමිතිය අර්ථ දැක්වීම සඳහා වෙනත් ආකාරයකින් අමුතු දෙයක් වනු ඇත. "ඊට අමතරව, එක්කෝ ඔපෙරන්ඩ් දෙකටම අංක ගණිතමය වර්ගයක් තිබිය යුතුය, නැතහොත් වම් ඔපෙරන්ඩ් සම්පූර්ණ වස්තු වර්ගයක් සඳහා දර්ශකයක් විය යුතු අතර දකුණු ඔපෙරන්ඩ්හි පූර්ණ සංඛ්‍යා වර්ගය තිබිය යුතුය." - දේවල් එකතු කරන බොහෝ අයට එය තේරුමක් නැත.
iheanyi

10
heiheanyi: එකතු කිරීම සාමාන්‍යයෙන් සංක්‍රමණික වේ - සාමාන්‍යයෙන් එය එකම වර්ගයේ මෙහෙයුම් දෙකක් ගනී. දර්ශක එකතු කිරීම මඟින් ඔබට දර්ශකයක් සහ පූර්ණ සංඛ්‍යාවක් එක් කිරීමට ඉඩ දෙයි, නමුත් දර්ශක දෙකක් නොවේ. IMHO දැනටමත් ප්‍රමාණවත් තරම් අමුතු විශේෂ අවස්ථාවක් වන අතර, දර්ශකය වම් ක්‍රියාකාරිත්වය වීමට අවශ්‍ය වීම සැලකිය යුතු බරක් නොවනු ඇත. (සමහර භාෂාවන් නූල් සම්මුතිය සඳහා "+" භාවිතා කරයි; එය නිසැකවම සංක්‍රමණශීලී නොවේ.)
කීත් තොම්සන්

3
up සුපර්කැට්, එය ඊටත් වඩා නරකයි. එයින් අදහස් වන්නේ සමහර විට x + 1! = 1 + x. එය එකතු කිරීමේ අනුබද්ධ දේපල සම්පූර්ණයෙන්ම උල්ලං would නය කරයි.
iheanyi

3
heiheanyi: මම හිතන්නේ ඔබ අදහස් කළේ සංක්‍රමණික දේපලක්; බොහෝ ක්‍රියාත්මක කිරීම් වලදී (1LL + 1U) -2! = 1LL + (1U-2) එකතු කිරීම දැනටමත් සහායක නොවේ. ඇත්ත වශයෙන්ම, මෙම වෙනස දැනට නොමැති සමහර අවස්ථාවන් අනුබද්ධ කරයි, උදා: 3U + (UINT_MAX-2L) සමාන වේ (3U + UINT_MAX) -2. වඩා හොඳ දෙය නම්, භාෂාවට ප්‍රවර්ධනය කළ හැකි පූර්ණ සංඛ්‍යා සහ වීජීය මුදු “ඔතා” ගැනීම සඳහා නව විශේෂ වර්ග එකතු කිරීම ය, එවිට ring16_t65535 ක් ඇති 2 ට 2 ක් එකතු කිරීමෙන් ප්‍රමාණයෙන්ring16_t 1 ක අගයක් ලැබෙනු ඇත . int
සුපර් කැට්

196

ඇත්ත වශයෙන්ම

 ("ABCD"[2] == 2["ABCD"]) && (2["ABCD"] == 'C') && ("ABCD"[2] == 'C')

මෙයට ප්‍රධාන හේතුව වූයේ 70 දශකයේ දී සී නිර්මාණය කරන විට පරිගණකවලට එතරම් මතකයක් නොතිබීමයි (64KB ගොඩක් විය), එබැවින් සී සම්පාදකයා සින්ටැක්ස් පරීක්ෂාව සිදු නොකළේය. ඒ නිසා " X[Y]" ඒ වෙනුවට අන්ධ ලෙස පරිවර්තනය කර " *(X+Y)"

මෙය " +=" සහ " ++" සින්ටැක්ස් ද පැහැදිලි කරයි . " A = B + C" ආකෘතියේ ඇති සෑම දෙයක්ම එකම සම්පාදිත ස්වරූපයක් ඇත. B යනු A හා සමාන වස්තුවක් නම් එකලස් මට්ටමේ ප්‍රශස්තිකරණයක් ලබා ගත හැකිය. නමුත් සම්පාදකයා එය හඳුනා ගැනීමට තරම් දීප්තිමත් නොවූ බැවින් සංවර්ධකයාට ( A += C) කිරීමට සිදු විය. ඒ හා සමානව, නම් Cවූ 1, වෙනස් එකලස් මට්ටමේ ප්රශස්තිකරණය ලබා ගත හැකි, සම්පාදකවරයා එය හඳුනාගත නැති නිසා විය, නැවත එය පැහැදිලි කර ගැනීමට සංවර්ධක විය. (වඩාත් මෑතකදී සම්පාදකයින් එසේ කරයි, එබැවින් මෙම වාක්‍ය ඛණ්ඩ මේ දිනවල බොහෝ දුරට අනවශ්‍යය)


127
ඇත්ත වශයෙන්ම, එය අසත්‍යය ලෙස තක්සේරු කරයි; පළමු පදය "ABCD" [2] == 2 ["ABCD"] සත්‍ය ලෙස තක්සේරු කරයි, නැතහොත් 1, සහ 1! = 'C': D
ජොනතන් ලෙෆ්ලර්

8
On ජොනතන්: මෙම පෝස්ට් එකේ මුල් මාතෘකාව සංස්කරණය කිරීමට එකම අවිනිශ්චිතතාව හේතු වේ. අපි සමාන ලකුණු ගණිතමය සමානතාව, කේත වාක්‍ය ඛණ්ඩය හෝ ව්‍යාජ කේතයද? මම ගණිතමය සමානාත්මතාවය ගැන තර්ක කරමි, නමුත් අපි කේතය ගැන කතා කරන බැවින්, කේත සින්ටැක්ස් ප්‍රකාරව අපි සියල්ල නරඹන බැවින් අපට ගැලවිය නොහැක.
දීනා

19
මෙය මිථ්‍යාවක් නොවේද? මම අදහස් කළේ + = සහ ++ ක්‍රියාකරුවන් නිර්මාණය කර ඇත්තේ සම්පාදකයා සඳහා සරල කිරීම සඳහා ද? සමහර කේත ඔවුන් සමඟ වඩාත් පැහැදිලි වන අතර, සම්පාදකයා එය සමඟ කුමක් කළත් එය ප්‍රයෝජනවත් සින්ටැක්ස් වේ.
තෝමස් පැඩ්‍රොන්-මැකාති

6
+ = සහ ++ තවත් වැදගත් වාසියක් ඇත. ඇගයීමේදී වම් පැත්ත යම් විචල්‍යයක් වෙනස් කරන්නේ නම්, වෙනස සිදු වන්නේ එක් වරක් පමණි. a = a + ...; එය දෙවරක් කරනු ඇත.
ජොහැන්නස් ෂෝබ් -

8
නැත - "ABCD" [2] == * ("ABCD" + 2) = * ("CD") = 'C'. නූලක් විරූපණය කිරීමෙන් ඔබට උපස්ථරයක් නොව වර්‍ගයක් ලැබේ
MSalters

55

දීනාගේ ගැටලුව ගැන කිසිවෙකු සඳහන් කර නැති බව පෙනේ sizeof:

ඔබට දර්ශකයක් වෙත පූර්ණ සංඛ්‍යාවක් එක් කළ හැකිය, ඔබට දර්ශක දෙකක් එකට එකතු කළ නොහැක. ඒ ආකාරයට පූර්ණ සංඛ්‍යාවක් සඳහා දර්ශකයක් හෝ දර්ශකයකට පූර්ණ සංඛ්‍යාවක් එකතු කරන විට, සම්පාදකයා සෑම විටම දන්නේ කුමන බිට් ප්‍රමාණයද සැලකිල්ලට ගත යුතුද යන්නයි.


1
පිළිගත් පිළිතුරේ අදහස් දැක්වීමේදී මේ පිළිබඳව තරමක් පරිපූර්ණ සංවාදයක් ඇත. සංස්කරණයේදී මුල් ප්‍රශ්නයට කළ සංවාදය මා සඳහන් කළ නමුත් ප්‍රමාණය පිළිබඳ ඔබේ වලංගු සැලකිල්ල කෙලින්ම ආමන්ත්‍රණය කළේ නැත. SO හි මෙය වඩාත් හොඳින් කරන්නේ කෙසේදැයි විශ්වාස නැත. මම මූලාරම්භයට තවත් සංස්කරණයක් කළ යුතුද? ප්‍රශ්නය?
දීනා

49

ප්‍රශ්නයට වචනාර්ථයෙන් පිළිතුරු දීමට. එය සැමවිටම සත්‍ය නොවේx == x

double zero = 0.0;
double a[] = { 0,0,0,0,0, zero/zero}; // NaN
cout << (a[5] == 5[a] ? "true" : "false") << endl;

මුද්රණ

false

27
ඇත්ත වශයෙන්ම "නන්" තමාට සමාන නොවේ: cout << (a[5] == a[5] ? "true" : "false") << endl;වේ false.
TrueY

9
R සත්‍යය: ඔහු විශේෂයෙන් සඳහන් කළේ නාන් නඩුව සඳහා (සහ x == xඑය සැමවිටම සත්‍ය නොවේ). මම හිතන්නේ එය ඔහුගේ අභිප්‍රාය විය. එබැවින් ඔහු තාක්‍ෂණිකව නිවැරදි ය (සමහර විට ඔවුන් පවසන පරිදි හොඳම ආකාරයේ නිවැරදි!).
ටිම්

4
ප්‍රශ්නය C ගැන ය, ඔබේ කේතය C කේතය නොවේ. එහි ද වේ NANදී <math.h>, වඩා යහපත් වන 0.0/0.0නිසා, 0.0/0.0යුනියන් විට ය __STDC_IEC_559__අර්ථ දක්වා නැත (බොහෝ නිර්මාණයන් නිර්වචනය කරන්නේ නැහැ __STDC_IEC_559__, නමුත් බොහෝ නිර්මාණයන් මත 0.0/0.0වැඩ තවමත්)
12431234123412341234123

26

මෙම අවලස්සන වාක්‍ය ඛණ්ඩය “ප්‍රයෝජනවත්” විය හැකි බව මම සොයා ගතිමි, නැතහොත් එකම අරාවකට ස්ථාන යොමු කරන දර්ශක සමූහයක් සමඟ ගනුදෙනු කිරීමට ඔබට අවශ්‍ය විට අවම වශයෙන් ඉතා විනෝදජනක විය හැකිය. එමඟින් කූඩුවල වර්ග වරහන් ප්‍රතිස්ථාපනය කර කේතය වඩාත් කියවිය හැකිය!

int a[] = { 2 , 3 , 3 , 2 , 4 };
int s = sizeof a / sizeof *a;  //  s == 5

for(int i = 0 ; i < s ; ++i) {  

           cout << a[a[a[i]]] << endl;
           // ... is equivalent to ... 
           cout << i[a][a][a] << endl;  // but I prefer this one, it's easier to increase the level of indirection (without loop)

}

ඇත්ත වශයෙන්ම, සැබෑ කේතයේ ඒ සඳහා කිසිදු ප්‍රයෝජනයක් නොමැති බව මට හොඳටම විශ්වාසයි, නමුත් එය කෙසේ වෙතත් මට සිත්ගන්නාසුළු විය :)


ඔබ දකින විට ඔබ i[a][a][a]සිතන්නේ මම එක්කෝ අරාවකට දර්ශකයක් හෝ අරාවකට හෝ අරාවකට aදර්ශකයේ අරාවක් ... සහ එය දර්ශකයකි. ඔබ දකින විට a[a[a[i]]], ඔබ සිතන්නේ a යනු අරාවකට හෝ අරාවකට iදර්ශකයක් වන අතර එය දර්ශකයකි.
12431234123412341234123

1
වාව්! මෙම "මෝඩ" අංගයේ ඉතා සිසිල් භාවිතයකි. සමහර ගැටළු වලදී ඇල්ගොරිතම තරඟයේදී ප්‍රයෝජනවත් විය හැක))
සර්ජ් බ්‍රූසොව්

26

හොඳ ප්‍රශ්නයක් / පිළිතුරු.

C දර්ශකයන් සහ අරා එක සමාන නොවන බව පෙන්වා දීමට අවශ්‍යය , මෙම අවස්ථාවේ දී වෙනස අත්‍යවශ්‍ය නොවේ.

පහත ප්‍රකාශ සලකා බලන්න:

int a[10];
int* p = a;

දී a.out, සංකේතය aඅරාවෙහි ආරම්භය වන pලිපිනයක වන අතර සංකේතය දර්ශකයක් ගබඩා කර ඇති ලිපිනයක ඇති අතර එම මතක ස්ථානයේ ඇති දර්ශකයේ අගය අරාවේ ආරම්භය වේ.


2
නැත, තාක්ෂණික වශයෙන් ඒවා සමාන නොවේ. ඔබ සමහරක් b int * const ලෙස අර්ථ දක්වා එය අරාවකට යොමු කරන්නේ නම්, එය තවමත් දර්ශකයක් වන අතර, එයින් අදහස් වන්නේ සංකේත වගුවේ b යනු ලිපිනයක් ගබඩා කරන මතක ස්ථානයක් වන අතර එමඟින් අරාව ඇති තැනට යොමු වේ. .
පොලිටින්කර්

4
ඉතා හොඳ කරුණක්. එක් මොඩියුලයක ගෝලීය සංකේතයක් char s [100] ලෙස අර්ථ දැක්වීමේදී එය බාහිර වර්‍ග * ලෙස ප්‍රකාශ කරන විට මට ඉතා නරක දෝෂයක් ඇති බව මට මතකයි; වෙනත් මොඩියුලයක. ඒ සියල්ල එකට සම්බන්ධ කිරීමෙන් පසුව වැඩසටහන ඉතා අමුතු ලෙස හැසිරුණි. මොකද බාහිර ප්‍රකාශනය භාවිතා කරන මොඩියුලය අරාවෙහි ආරම්භක බයිට් වර්‍ගයට දර්ශකයක් ලෙස භාවිතා කරයි.
ජෝජියෝ

1
මුලදී, සීගේ ආච්චිලා සීය බීසීපීඑල් හි අරාව දර්ශකයක් විය. ඔබ (මම සී කිරීමට තනය කර ඇත) ලියන විට ඔයා මොනවද, වේ int a[10]'ඒ' නමින් පහිටුම් දක්වනය, වෙනත් තැන්වල, පූර්ණ සංඛ්යා 10 ක් තරම් ගබඩා පෙන්වා ඇති විය. මේ අනුව + i සහ j + i එකම ස්වරූපයක් ඇත: මතක ස්ථාන කිහිපයක අන්තර්ගතය එක් කරන්න. ඇත්ත වශයෙන්ම, මම සිතන්නේ බීසීපීඑල් ටයිප් රහිත බැවින් ඒවා සමාන විය. බීසීපීඑල් තනිකරම වචන-නැඹුරු වූ නිසා (වචන ආමන්ත්‍රණය කරන යන්ත්‍රවල ද) ප්‍රමාණයේ පරිමාණය අදාළ නොවේ.
ඩේව්

මම වෙනස තේරුම් ගැනීමට හොඳම ක්රමය සංසන්දනය කිරීමට සිතන්නේ int*p = a;කිරීමට int b = 5; අග, "ආ" දී සහ "5" ස්ථාවර අගය වන අතර "5", යන දෙකම පූර්ණ සංඛ්යා වන අතර, නමුත් "ආ" විචල්ය වේ. ඒ හා සමානව, "p" සහ "a" යන දෙකම අක්ෂරයක ලිපින වේ, නමුත් "a" යනු ස්ථාවර අගයකි.
ජේම්ස් කුරන්

20

සී හි දර්ශකයන් සඳහා, අපට තිබේ

a[5] == *(a + 5)

ඒ වගේම

5[a] == *(5 + a)

එබැවින් එය සත්‍යයකි a[5] == 5[a].


15

පිළිතුරක් නොව, සිතුවිලි සඳහා ආහාර කිහිපයක් පමණි. පංතියේ අධි බර පැටවූ දර්ශක / ග්‍රාහක ක්‍රියාකරු සිටී නම්, ප්‍රකාශනය ක්‍රියා 0[x]නොකරනු ඇත:

class Sub
{
public:
    int operator [](size_t nIndex)
    {
        return 0;
    }   
};

int main()
{
    Sub s;
    s[0];
    0[s]; // ERROR 
}

අපට int පන්තියට ප්‍රවේශය නොමැති බැවින් මෙය කළ නොහැක:

class int
{
   int operator[](const Sub&);
};

2
class Sub { public: int operator[](size_t nIndex) const { return 0; } friend int operator[](size_t nIndex, const Sub& This) { return 0; } };
බෙන් වොයිගට්

1
ඔබ එය සම්පාදනය කිරීමට උත්සාහ කර තිබේද? පංතියෙන් පිටත ක්‍රියාත්මක කළ නොහැකි ක්‍රියාකරුවන් සමූහයක් ඇත (එනම් ස්ථිතික නොවන කාර්යයන් ලෙස)!
අජේ

3
අපොයි, ඔබ හරි. " operator[]හරියටම එක් පරාමිතියක් සහිත ස්ථිතික නොවන සාමාජික ශ්‍රිතයක් විය යුතුය." එම සීමාව මට හුරු පුරුදු විය operator=, එය අදාළ වේ යැයි සිතුවේ නැත [].
බෙන් වොයිගට්

1
ඇත්ත වශයෙන්ම, ඔබ []ක්‍රියාකරුගේ අර්ථ දැක්වීම වෙනස් කළහොත් එය නැවත කිසි දිනෙක සමාන නොවනු ඇත ... a[b]සමාන නම් *(a + b)සහ ඔබ මෙය වෙනස් කරන්නේ නම්, ඔබට අධික බර පැටවීමට සිදු වන int::operator[](const Sub&);අතර intඑය පන්තියක් නොවේ ...
ලුයිස් කොලරාඩෝ

8
මෙය ... නොවේ ... සී.
MD XF

11

ටෙඩ් ජෙන්සන් විසින් රචිත A TUTORIAL ON POINTERS AND ARRAYS IN C හි එය ඉතා හොඳ පැහැදිලි කිරීමක් ඇත .

ටෙඩ් ජෙන්සන් එය මෙසේ පැහැදිලි කළේය.

ඇත්ත වශයෙන්ම, මෙය සත්‍යයකි, එනම් යමෙකු ලියන ඕනෑම තැනක a[i]එය *(a + i) කිසිදු ගැටළුවක් නොමැතිව ප්‍රතිස්ථාපනය කළ හැකිය . ඇත්ත වශයෙන්ම, සම්පාදකයා ඕනෑම අවස්ථාවක එකම කේතය නිර්මාණය කරයි. මේ අනුව, දර්ශක අංක ගණිතය අරාව සුචිගත කිරීම හා සමාන බව අපට පෙනේ. එක්කෝ සින්ටැක්ස් එකම ප්‍රති .ලය ලබා දෙයි.

දර්ශකයන් සහ අරා එකම දේ යැයි මෙය නොකියයි, ඒවා එසේ නොවේ. අප කියන්නේ අරාවෙහි දී ඇති මූලද්‍රව්‍යයක් හඳුනා ගැනීම සඳහා අපට සින්ටැක්ස් දෙකක් තෝරා ගත හැකි බවයි, එකක් අරාව සුචිගත කිරීම සහ අනෙක සමාන ප්‍රති .ල ලබා දෙන දර්ශක අංක ගණිතය භාවිතා කිරීම ය.

දැන්, මෙම අන්තිම ප්‍රකාශනය දෙස බලන විට, එහි කොටසක් .. (a + i)යනු + ක්‍රියාකරු සහ සී ප්‍රකාශයේ සරල එකතු කිරීමකි, එවැනි ප්‍රකාශනයක් සංක්‍රමණශීලී බව. එනම් (a + i) සමාන වේ (i + a). මේ අනුව අපට පහසුවෙන් ලිවිය *(i + a)හැකිය *(a + i). ඒත් *(i + a)එන්න තිබුනා i[a]! මේ සියල්ලෙන් කුතුහලය දනවන සත්‍යය නම්:

char a[20];

ලේඛන

a[3] = 'x';

ලිවීමට සමාන වේ

3[a] = 'x';

4
a + i සරල එකතු කිරීමක් නොවේ, මන්ද එය දර්ශක අංක ගණිතයයි. a හි මූලද්‍රව්‍යයේ ප්‍රමාණය 1 (char) නම්, ඔව්, එය නිඛිල + හා සමාන වේ. නමුත් එය (උදා) පූර්ණ සංඛ්‍යාවක් නම්, එය + 4 * i ට සමාන විය හැකිය.
ඇලෙක්ස් බ්‍රවුන්

Lex ඇලෙක්ස්බ්‍රවුන් ඔව්, එය දර්ශක අංක ගණිතය වන අතර, ඔබ මුලින්ම 'අ' (වර්‍ග *) බවට පත් නොකළහොත් (අන්තිම අක්ෂර 4 ක් යැයි උපකල්පනය කර) ඔබේ අවසාන වාක්‍යය වැරදිය. පොයින්ටර් අංක ගණිතයේ සත්‍ය වටිනාකමේ ප්‍රති result ල මත මෙතරම් පිරිසක් රැඳී සිටින්නේ මන්දැයි මට තේරෙන්නේ නැත. පොයින්ටර් අංක ගණිතයේ සම්පූර්ණ අරමුණ වන්නේ යටින් පවතින දර්ශක අගයන් වියුක්ත කිරීම සහ ලිපින අගයන්ට වඩා වස්තූන් හැසිරවීම ගැන ක්‍රමලේඛකයාට සිතීමට ඉඩ දීමයි.
jschultz410

8

ප්‍රශ්නයට පිළිතුරු ලැබී ඇති බව මම දනිමි, නමුත් මෙම පැහැදිලි කිරීම බෙදා ගැනීමට මට නොහැකි විය.

මම Compiler නිර්මාණය මූලධර්ම මතක, අපි උපකල්පනය කරමු aයනු intපෙළගැස්මකින් සහ ප්රමාණය int2 බයිට් වන අතර, සහ සඳහා මූලික ලිපිනය a1000 වේ.

ක්‍රියා කරන්නේ කෙසේද a[5]->

Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010

නිසා,

ඒ හා සමානව c කේතය 3-ලිපින කේතයකට 5[a]බෙදූ විට -> බවට පත්වේ

Base Address of your Array a + (size of(data type for array a)*5)
i.e. 1000 + (2*5) = 1010 

එබැවින් මූලික වශයෙන් ප්‍රකාශ දෙකම මතකයේ එකම ස්ථානයකට යොමු වන අතර එබැවින් a[5] = 5[a].

අරා වල negative ණ දර්ශක C හි වැඩ කිරීමට හේතුව මෙම පැහැදිලි කිරීම ද වේ.

එනම් මා ප්‍රවේශ වුවහොත් a[-5]එය මට ලබා දෙනු ඇත

Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990

එය 990 ස්ථානයේ මට වස්තුව නැවත ලබා දෙනු ඇත.


6

දී සී පෙලගැස්මක් , arr[3]හා 3[arr]සමාන වේ, හා ඔවුන්ගේ සමාන පහිටුම් දක්වනය අංකන වේ *(arr + 3)කිරීමට *(3 + arr). එහෙත් ඊට ප්රතිවිරුද්ධව [arr]3හෝ [3]arrනිවැරදි නොවන අතර කාරක රීති දෝෂයක් බවට හේතු වනු ඇත, ලෙස (arr + 3)*හා (3 + arr)*වලංගු ප්රකාශන නොවේ. හේතුව, විරූපණ ක්‍රියාකරු ප්‍රකාශනය මඟින් ලබා දෙන ලිපිනයට පෙර තැබිය යුතු අතර ලිපිනයෙන් පසුව නොවේ.


6

c සම්පාදකයේ

a[i]
i[a]
*(a+i)

අරාවෙහි මූලද්‍රව්‍යයක් යොමු කිරීමට විවිධ ක්‍රම වේ! (සෑම අතින්ම නොවේ)


5

දැන් ඉතිහාසය ටිකක්. වෙනත් භාෂාවන් අතර, බීසීපීඑල් සී හි මුල් සංවර්ධනයට තරමක් විශාල බලපෑමක් ඇති කළේය. ඔබ BCPL හි අරාව ප්‍රකාශයට පත් කළේ නම්:

let V = vec 10

එය සත්‍ය වශයෙන්ම වචන 11 ක් වෙන් කර ඇත, 10 නොවේ. සාමාන්‍යයෙන් V යනු පළමුවැන්න වන අතර වහාම පහත සඳහන් වචනයේ ලිපිනය අඩංගු වේ. C මෙන් නොව V නම් කිරීම එම ස්ථානයට ගොස් අරාවේ ශුන්‍ය මූලද්‍රව්‍යයේ ලිපිනය ලබා ගත්තේය. එබැවින් BCPL හි අරාව නිර්‍මාණ කිරීම,

let J = V!5

J = !(V + 5)අරාවෙහි මූලික ලිපිනය ලබා ගැනීම සඳහා V ලබා ගැනීම අවශ්‍ය වූ හෙයින් (BCPL සින්ටැක්ස් භාවිතා කරමින්) ඇත්ත වශයෙන්ම කළ යුතුව තිබුණි . මේ අනුව V!5සහ 5!Vසමාන පද විය. පුරාවෘත්ත නිරීක්ෂණයක් ලෙස, ඩබ්ලිව්.ඒ.එෆ්.එල්. මෙය මීට වසර 35 ත් 40 ත් අතර කාලයක සිට පැවත එන බැවින් මගේ මතකය ටිකක් මලකඩ ය. :)

අමතර ගබඩා කිරීමේ වචනය සමඟ බෙදා හැරීමේ නවෝත්පාදනය සහ සම්පාදකයා විසින් අරාව නම් කරන විට එහි මූලික ලිපිනය ඇතුළත් කිරීම පසුව පැමිණියේය. සී ඉතිහාස පත්‍රයට අනුව මෙය සිදු වූයේ ව්‍යුහයන් සී ට එකතු කරන අවස්ථාවේ දී ය.

!BCPL හි ඒකීය උපසර්ග ක්‍රියාකරුවෙකු සහ ද්විමය ඉන්ෆික්ස් ක්‍රියාකරුවෙකු වූ බව සලකන්න . ද්විමය ආකෘතියට ඉන්ඩෙක්ෂන් කිරීමට පෙර ඔපෙරන්ඩ් දෙක එකතු කිරීමක් ඇතුළත් විය. BCPL (සහ B) හි දිශානත ස්වභාවය අනුව මෙය සැබවින්ම අර්ථවත් විය. දත්ත වර්ග ලබා ගන්නා විට C හි “දර්ශකය සහ පූර්ණ සංඛ්‍යාව” සීමා කිරීම අවශ්‍ය වූ අතර එය sizeofදෙයක් බවට පත්විය.


1

හොඳයි, මෙය භාෂා සහාය නිසා පමණක් කළ හැකි ලක්ෂණයකි.

සම්පාදකයා අර්ථ නිරූපණය a[i]කරන *(a+i)අතර ප්‍රකාශනය 5[a]ඇගයීමට ලක් කරයි *(5+a). එකතු කිරීම සංක්‍රමණික බැවින් දෙකම සමාන බව පෙනේ. එබැවින් ප්‍රකාශනය ඇගයීමට ලක් කරයි true.


අතිරික්තයක් වුවද මෙය පැහැදිලි, සංක්ෂිප්ත හා කෙටි ය.
බිල් කේ

0

සී

 int a[]={10,20,30,40,50};
 int *p=a;
 printf("%d\n",*p++);//output will be 10
 printf("%d\n",*a++);//will give an error

පොයින්ටරය යනු "විචල්ය" ය

අරාවෙහි නම "සිහිවටන" හෝ "සමාන පදයක්" වේ

p++;වලංගු නමුත් a++වලංගු නොවේ

a[2] 2 [a] ට සමාන වේ, මන්ද මේ දෙකෙහිම අභ්‍යන්තර ක්‍රියාකාරිත්වය වේ

අභ්‍යන්තරව ගණනය කරනු ලබන “පොයින්ටර් අංක ගණිතය”

*(a+3) සමාන *(3+a)


-4

දර්ශක වර්ග

1) දත්ත වෙත යොමු කිරීම

int *ptr;

2) දත්ත වෙත සංයුක්ත දර්ශකය

int const *ptr;

3) සංයුක්ත දත්ත සඳහා const pointer

int const *const ptr;

සහ අරා අපගේ ලැයිස්තුවෙන් (2) වර්ගයකි.
ඔබ වරකට අරාව නිර්වචනය කරන විට එම දර්ශකයේ එක් ලිපිනයක් ආරම්භ වේ
. අපගේ වැඩසටහනේ නියත අගය වෙනස් කිරීමට හෝ වෙනස් කිරීමට අපට නොහැකි බව අප දන්නා හෙයින් එය සම්පාදනය කිරීමේදී දෝෂයක් ඇති කරයි කාලය

මෙම ප්රධාන වෙනස මා සොයාගෙන ඇත ...

අපට දර්ශකය ලිපිනයකින් නැවත ආරම්භ කළ හැකි නමුත් අරාව සමඟ එකම අවස්ථාව නොවේ.

======
සහ ඔබේ ප්‍රශ්නයට ආපසු යන්න ...
a[5]වෙන කිසිවක් නොව අපගේ ලැයිස්තුවේ (2) ආකාරයේ දර්ශකයක් මෙන් ලිපිනය (මිනිසුන් එය මූලික ලිපිනය ලෙස හඳුන්වයි) *(a + 5)
පහසුවෙන් තේරුම් ගත හැකිය - එම ක්‍රියාකරු විය හැකිය දර්ශකය සමඟ ප්‍රතිස්ථාපනය කළ හැකිය.
a
[]*

ඉතින් අවසානයේ ...

a[5] == *(a +5) == *(5 + a) == 5[a] 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.