Ці з'яўляюцца гэтыя два метаду ўстаноўкі паказальнікаў роўныя адзін аднаму тое ж самае?

Мне цікава, калі ў мяне ёсць два паказальніка

int *x = (int *)malloc(sizeof(int));
int *y;

і я хачу, каб у пазначыць адрас х, з'яўляецца

y = x;

гэтак жа, як

y = &*x;

?

4
Ні адзін з гэтых заданняў прыводзіць да ў «кропкі [я] у адрас х». Абодва з іх усталяваць у роўны х. Гэта значыць, яны паказваюць на адзін і вылучанага аб'екта. Да C ці C ++ праграміста, «адрас х», як правіла, інтэрпрэтуюцца з як & х , а не адрас, які паказвае на х.
дададзена аўтар Adrian McCarthy, крыніца
Ні адзін з гэтых заданняў прыводзіць да ў «кропкі [я] у адрас х». Абодва з іх усталяваць у роўны х. Гэта значыць, яны паказваюць на адзін і вылучанага аб'екта. Да C ці C ++ праграміста, «адрас х», як правіла, інтэрпрэтуюцца з як & х , а не адрас, які паказвае на х.
дададзена аўтар Adrian McCarthy, крыніца
@JAB: Пытанне заўважана C, а не C ++, таму я не згадаў правілы C ++. У C ++, калі х гэта итератор, то * х выклікае пэўны карыстальнік (ну, верагодна, бібліятэка вызначаныя) перагружаны аператар, а таксама любыя правілы аб калапсе & * х у х не будзе прымяняцца. Вядома C ++ ёсць паказальнікі C-стылі і ўбудаваны унарный & і * аператары. C ++ не прыняў да правіла спецыяльнага выпадку Кассиопеяна для & * х . У любым выпадку, улічваючы заяву Int * х , х гэта звычайны паказальнік, а не итератора. Калі ў вас ёсць пытанні адносна итераторов C ++, вы можаце размясціць яго асобна.
дададзена аўтар Keith Thompson, крыніца
@JAB: Пытанне заўважана C, а не C ++, таму я не згадаў правілы C ++. У C ++, калі х гэта итератор, то * х выклікае пэўны карыстальнік (ну, верагодна, бібліятэка вызначаныя) перагружаны аператар, а таксама любыя правілы аб калапсе & * х у х не будзе прымяняцца. Вядома C ++ ёсць паказальнікі C-стылі і ўбудаваны унарный & і * аператары. C ++ не прыняў да правіла спецыяльнага выпадку Кассиопеяна для & * х . У любым выпадку, улічваючы заяву Int * х , х гэта звычайны паказальнік, а не итератора. Калі ў вас ёсць пытанні адносна итераторов C ++, вы можаце размясціць яго асобна.
дададзена аўтар Keith Thompson, крыніца
Чаму вы хочаце напісаць у = & * х у першую чаргу?
дададзена аўтар Keith Thompson, крыніца
Чаму вы хочаце напісаць у = & * х у першую чаргу?
дададзена аўтар Keith Thompson, крыніца
Мне было цікава, калі ёсць розніца.
дададзена аўтар user1876508, крыніца
Мне было цікава, калі ёсць розніца.
дададзена аўтар user1876508, крыніца
@KeithThompson Калі я ўспамінаю сваю працу з LLVM правільна, калі вы пішаце на C ++ код, х итератор, і у гэта паказальнік павінен быць вернуты з спосаб C-інтэрфейс. На жаль, у мяне няма майго кода са мной у той момант, каб праверыць, калі я правільна памятаць, што, такім чынам каментар ад каго-то з вялікім веданнем C ++ будзе ацэнены.
дададзена аўтар JAB, крыніца
@KeithThompson Калі я ўспамінаю сваю працу з LLVM правільна, калі вы пішаце на C ++ код, х итератор, і у гэта паказальнік павінен быць вернуты з спосаб C-інтэрфейс. На жаль, у мяне няма майго кода са мной у той момант, каб праверыць, калі я правільна памятаць, што, такім чынам каментар ад каго-то з вялікім веданнем C ++ будзе ацэнены.
дададзена аўтар JAB, крыніца
(Рэальны пытанне, вядома ж, тое, што адбываецца, калі х == NULL )
дададзена аўтар Elazar, крыніца
AFAIK, так. * Х які называе, & * х яго адрас, які з'яўляецца х. не павінна быць ніякіх пабочных эфектаў, якія ўдзельнічаюць.
дададзена аўтар Elazar, крыніца
(Рэальны пытанне, вядома ж, тое, што адбываецца, калі х == NULL )
дададзена аўтар Elazar, крыніца
@anishsane Я думаю, вы маеце рацыю, але я буду рады бачыць доказ. (Не прыклад).
дададзена аўтар Elazar, крыніца
@anishsane Я думаю, вы маеце рацыю, але я буду рады бачыць доказ. (Не прыклад).
дададзена аўтар Elazar, крыніца
^^ @ Элазар: Пратэставаны GCC -S . Але на самой справе, я буду здзіўлены, калі некаторыя кампілятар ставіцца да іх па-рознаму.
дададзена аўтар anishsane, крыніца
^^ @ Элазар: Пратэставаны GCC -S . Але на самой справе, я буду здзіўлены, калі некаторыя кампілятар ставіцца да іх па-рознаму.
дададзена аўтар anishsane, крыніца
@Elazar: Гэта не мае значэння. Ён не адмовіць.
дададзена аўтар anishsane, крыніца
@Elazar: Гэта не мае значэння. Ён не адмовіць.
дададзена аўтар anishsane, крыніца

13 адказы

Ваша пытанне складаецца з двух частак, і гэта варта адзначыць, што яны не з'яўляюцца правільнымі:

Па-першае, вы спытаеце:

is
y = x;
the same as
y = &*x;

Since the dereference (*) and address-of (&) operators have the same precedence they will bind right to left, so

y = &*x;

гэтак жа, як:

y = &(*x);

І так, гэта дасць той жа эфект, у = х; Зараз, калі ў вас ёсць сумяшчальны кампілятар C, які варта літары закону, гэта будзе не толькі тое жа эфектыўна, што будзе быць такім жа, гэта звязана з падзелам 6.5.3.2 P3 з C Спецыфікацыя:

The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’.

If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted

So the compiler will see both the * and & together and omit them entirely.


У другой палове Вашага пытання Вы заявілі:

<�Код> Я хачу, каб у, каб паказаць на адрас х

Presumably you know that that's not what you're doing, but you're setting y to point to the same address as x instead. x of course has its own address and that could be set, but you'd need a different variable int **y = &x; assuming x is a valid value to be dereferenced.

8
дададзена
Там няма нічога няправільна аб прынятым адказе. Плакат вышэй адзначае, што калі кампілятар да нуля адносна 6.5.3.2 P3 стандарту C, гэтая надмернасць выдаляецца цалкам. Калі гэта не адпавядае стандарту, то надмернасць не выдаляецца, а маё апісанне (гэта значыць: Ускосна то адрас) вырашае гэтую заклапочанасць досыць без размяшчэння зборкі псеўда дапоўніць яго.
дададзена аўтар DevNull, крыніца
Калі х з'яўляецца пустым паказальнікам, то * х мае нявызначаны паводзіны пры * аператара вылічаецца. У & * х , стандарт відавочна паказана, што ні * , ні і вылічаецца, так што не вызначана паводзіны; <�Код> & * х эквівалентна х , за выключэннем таго, што гэта не які называе. (Наступнае зацвярджэнне, што «абмежаванні на аператары да гэтага часу ўжываецца" не мяняецца, што патрабаванне аб тым, што аперанд * не з'яўляецца нулявым не з'яўляецца стрымліваючым фактарам.) Правіла разбураецца & * х да X быў дададзены ў C99; у C89/C90, няма такога правіла, і & * х сапраўды мае нявызначаны паводзіны, калі х пустой паказальнік.
дададзена аўтар Keith Thompson, крыніца
@Elazar - Я выкарыстоўваю яго як коўдру заяву, таму што гэта лягчэй, што шлях, аднак з пункту гледжання мовы C гледжання (6.5.3.2 P4) гэта UB: Калі недапушчальнае значэнне прысвойваецца паказальніку, то паводзіны аднамеснай аператара * не вызначана.
дададзена аўтар Mike, крыніца
@Elazar - Такім чынам, гэтыя выразы не супадаюць - Сціраючы, павесіць там. Глядзіце маю спасылку на C спецыфікацыю у маёй абароне </я>? Гэта тычыцца першага, я думаю, што я зразумеў, што/чаму вы пыталіся. Калі ласка, глядзіце каментар ад @Keith. Я думаю, што гэта растлумачвае. Ды Int * х = NULL; INT у = * х; гэта УБ (6.5.3.2 Р4). Аднак Int * х = NULL; INT * у = & (* х); не з'яўляецца (6.5.3.2 P3), так як & * частка не будзе ацэнена. Адчуваеце розніцу?
дададзена аўтар Mike, крыніца
@Elazar - пры ўмове х з'яўляецца дапушчальным значэннем для разыменовываться з'яўляецца каментаром, які адносіцца да ўсяго адказу.
дададзена аўтар Mike, крыніца
Так, але я хачу ведаць, што адбудзецца, калі х <�я> не сапраўднае значэнне разыменовываться. Ці з'яўляецца гэта бяспечна? з'яўляецца гэта UB?
дададзена аўтар Elazar, крыніца
Вялікі дзякуй. Гэта менавіта тое, што я шукаў. Такім чынам, гэтыя выразы <�я> не </я> тое ж самае.
дададзена аўтар Elazar, крыніца
@KeithThompson вялікі. Так што я разумею, што фармальна эквівалентна, але не па-сапраўднаму партатыўным спосабам.
дададзена аўтар Elazar, крыніца
@ Mike Я ведаю розніцу; вядома у = * х гэта UB, але гэта не цікава. Я зразумеў, гэтыя выразы тыя ж заснаваныя на ваш каментар, а не на свой абноўлены адказ (і каментар Кіта). І так, гэта тое, што я хацеў бы ведаць.
дададзена аўтар Elazar, крыніца
і калі х NULL?
дададзена аўтар Elazar, крыніца

Ваша пытанне складаецца з двух частак, і гэта варта адзначыць, што яны не з'яўляюцца правільнымі:

Па-першае, вы спытаеце:

is
y = x;
the same as
y = &*x;

Since the dereference (*) and address-of (&) operators have the same precedence they will bind right to left, so

y = &*x;

гэтак жа, як:

y = &(*x);

І так, гэта дасць той жа эфект, у = х; Зараз, калі ў вас ёсць сумяшчальны кампілятар C, які варта літары закону, гэта будзе не толькі тое жа эфектыўна, што будзе быць такім жа, гэта звязана з падзелам 6.5.3.2 P3 з C Спецыфікацыя:

The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’.

If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted

So the compiler will see both the * and & together and omit them entirely.


У другой палове Вашага пытання Вы заявілі:

<�Код> Я хачу, каб у, каб паказаць на адрас х

Presumably you know that that's not what you're doing, but you're setting y to point to the same address as x instead. x of course has its own address and that could be set, but you'd need a different variable int **y = &x; assuming x is a valid value to be dereferenced.

8
дададзена
Там няма нічога няправільна аб прынятым адказе. Плакат вышэй адзначае, што калі кампілятар да нуля адносна 6.5.3.2 P3 стандарту C, гэтая надмернасць выдаляецца цалкам. Калі гэта не адпавядае стандарту, то надмернасць не выдаляецца, а маё апісанне (гэта значыць: Ускосна то адрас) вырашае гэтую заклапочанасць досыць без размяшчэння зборкі псеўда дапоўніць яго.
дададзена аўтар DevNull, крыніца
Калі х з'яўляецца пустым паказальнікам, то * х мае нявызначаны паводзіны пры * аператара вылічаецца. У & * х , стандарт відавочна паказана, што ні * , ні і вылічаецца, так што не вызначана паводзіны; <�Код> & * х эквівалентна х , за выключэннем таго, што гэта не які называе. (Наступнае зацвярджэнне, што «абмежаванні на аператары да гэтага часу ўжываецца" не мяняецца, што патрабаванне аб тым, што аперанд * не з'яўляецца нулявым не з'яўляецца стрымліваючым фактарам.) Правіла разбураецца & * х да X быў дададзены ў C99; у C89/C90, няма такога правіла, і & * х сапраўды мае нявызначаны паводзіны, калі х пустой паказальнік.
дададзена аўтар Keith Thompson, крыніца
@Elazar - Я выкарыстоўваю яго як коўдру заяву, таму што гэта лягчэй, што шлях, аднак з пункту гледжання мовы C гледжання (6.5.3.2 P4) гэта UB: Калі недапушчальнае значэнне прысвойваецца паказальніку, то паводзіны аднамеснай аператара * не вызначана.
дададзена аўтар Mike, крыніца
@Elazar - Такім чынам, гэтыя выразы не супадаюць - Сціраючы, павесіць там. Глядзіце маю спасылку на C спецыфікацыю у маёй абароне </я>? Гэта тычыцца першага, я думаю, што я зразумеў, што/чаму вы пыталіся. Калі ласка, глядзіце каментар ад @Keith. Я думаю, што гэта растлумачвае. Ды Int * х = NULL; INT у = * х; гэта УБ (6.5.3.2 Р4). Аднак Int * х = NULL; INT * у = & (* х); не з'яўляецца (6.5.3.2 P3), так як & * частка не будзе ацэнена. Адчуваеце розніцу?
дададзена аўтар Mike, крыніца
@Elazar - пры ўмове х з'яўляецца дапушчальным значэннем для разыменовываться з'яўляецца каментаром, які адносіцца да ўсяго адказу.
дададзена аўтар Mike, крыніца
Так, але я хачу ведаць, што адбудзецца, калі х <�я> не сапраўднае значэнне разыменовываться. Ці з'яўляецца гэта бяспечна? з'яўляецца гэта UB?
дададзена аўтар Elazar, крыніца
і калі х NULL?
дададзена аўтар Elazar, крыніца
Вялікі дзякуй. Гэта менавіта тое, што я шукаў. Такім чынам, гэтыя выразы <�я> не </я> тое ж самае.
дададзена аўтар Elazar, крыніца
@KeithThompson вялікі. Так што я разумею, што фармальна эквівалентна, але не па-сапраўднаму партатыўным спосабам.
дададзена аўтар Elazar, крыніца
@ Mike Я ведаю розніцу; вядома у = * х гэта UB, але гэта не цікава. Я зразумеў, гэтыя выразы тыя ж заснаваныя на ваш каментар, а не на свой абноўлены адказ (і каментар Кіта). І так, гэта тое, што я хацеў бы ведаць.
дададзена аўтар Elazar, крыніца

Яны <�моцны> функцыянальна эквівалентныя. Гэта эфектыўна «няпоўная копія».

Такім чынам, наступныя заданні дасягнення таго ж канчатковага выніку:

y=x;

y=&(*x);

Тым не менш, другая аперацыя зойме больш часу, каб выканаць, таму што, а не толькі прамое прызначэнне, вы выконваеце <�моцнай> Ускосна затым <�моцныя> Адрасы аперацыі. Кампілятар можа проста аптымізаваць гэта да у = х у любым выпадку, у залежнасці ад вашай сістэмы.

змяніць:


Як плакаце ніжэй заўвагі, калі ваш кампілятар падтрымлівае стандарт C, уключаючы 6.5.3.2 P3 стандарту C, гэта, безумоўна, будзе аптымізаваным, верагодна, на ўзроўні папярэдняй апрацоўкі да таго, як код нават кампіляцыі.

4
дададзена
Гэта будзе залежаць ад кампілятара, препроцессор, набору інструментаў і г.д. З майго бягучай ўстаноўкі GCC, такога роду надмернасці аптымізаванымі.
дададзена аўтар DevNull, крыніца
<�Код> Функцыянальна эквівалентна, у сэнсе, адны і тыя ж значэння, у выніку выхаду і г.д. Гэта не азначае, што яны будуць прымаць адны і тыя ж крокі, каб дасягнуць таго ж самага (дэтэрмінаваных) выхад. Я родам з статыстыкі/матэматыкі фону, таму я імкнуся быць вельмі канкрэтным, калі гаворка заходзіць пра гэта :)
дададзена аўтар DevNull, крыніца
<�Код> кампілятар можа проста аптымізаваць гэта ўніз - калі гэта сапраўдны C сумяшчальны кампілятар гэта <�б> будзе выдаліць абодва. Гэта частка спецыфікацыі C (гл мой адказ для даведкі).
дададзена аўтар Mike, крыніца
Вы <�я> упэўнены, гэта зойме больш часу? Калі яны сапраўды euqivalent, гэта не можа быць праўдай. Ускосна патрэбен аперанд.
дададзена аўтар Elazar, крыніца
Такім чынам, якія крокі будуць прынятыя, у псеўда-неоптимизированном зборкі? (Вядома, АСТ з'яўляецца <�я> не </я> тое ж самае.)
дададзена аўтар Elazar, крыніца
Я кажу пра псеўда зборкі. горшы выпадак. што можа адбыцца.
дададзена аўтар Elazar, крыніца

Яны <�моцны> функцыянальна эквівалентныя. Гэта эфектыўна «няпоўная копія».

Такім чынам, наступныя заданні дасягнення таго ж канчатковага выніку:

y=x;

y=&(*x);

Тым не менш, другая аперацыя зойме больш часу, каб выканаць, таму што, а не толькі прамое прызначэнне, вы выконваеце <�моцнай> Ускосна затым <�моцныя> Адрасы аперацыі. Кампілятар можа проста аптымізаваць гэта да у = х у любым выпадку, у залежнасці ад вашай сістэмы.

змяніць:


Як плакаце ніжэй заўвагі, калі ваш кампілятар падтрымлівае стандарт C, уключаючы 6.5.3.2 P3 стандарту C, гэта, безумоўна, будзе аптымізаваным, верагодна, на ўзроўні папярэдняй апрацоўкі да таго, як код нават кампіляцыі.

4
дададзена
<�Код> Функцыянальна эквівалентна, у сэнсе, адны і тыя ж значэння, у выніку выхаду і г.д. Гэта не азначае, што яны будуць прымаць адны і тыя ж крокі, каб дасягнуць таго ж самага (дэтэрмінаваных) выхад. Я родам з статыстыкі/матэматыкі фону, таму я імкнуся быць вельмі канкрэтным, калі гаворка заходзіць пра гэта :)
дададзена аўтар DevNull, крыніца
Гэта будзе залежаць ад кампілятара, препроцессор, набору інструментаў і г.д. З майго бягучай ўстаноўкі GCC, такога роду надмернасці аптымізаванымі.
дададзена аўтар DevNull, крыніца
<�Код> кампілятар можа проста аптымізаваць гэта ўніз - калі гэта сапраўдны C сумяшчальны кампілятар гэта <�б> будзе выдаліць абодва. Гэта частка спецыфікацыі C (гл мой адказ для даведкі).
дададзена аўтар Mike, крыніца
Вы <�я> упэўнены, гэта зойме больш часу? Калі яны сапраўды euqivalent, гэта не можа быць праўдай. Ускосна патрэбен аперанд.
дададзена аўтар Elazar, крыніца
Такім чынам, якія крокі будуць прынятыя, у псеўда-неоптимизированном зборкі? (Вядома, АСТ з'яўляецца <�я> не </я> тое ж самае.)
дададзена аўтар Elazar, крыніца
Я кажу пра псеўда зборкі. горшы выпадак. што можа адбыцца.
дададзена аўтар Elazar, крыніца

Яны альбо сапраўды гэтак жа, па вызначэнні, ці амаль тое ж самае, у залежнасці ад таго, якой версіі стандарту C вы маеце справу з.

У ISO C99 і C11, мы маем наступную фармулёўку (са спасылкай на N1570 C11 праект) у 6.5.3.2:

The unary & operator yields the address of its operand. If the operand has type "type", the result has type "pointer to type". If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.

Таму, улічваючы:

int *x = /* whatever */;
int *y;

гэтыя два дакладна эквівалентныя, , нават калі х пусты паказальнік :

y = x;
y = &*x;

Without the special-case rule, the behavior would be undefined, because the behavior of the * operator is defined only if its operand is a valid non-null pointer. But since the * is never evaluated, it has no behavior here, defined or otherwise. (The fact that, unlike x, &*x is not an lvalue is not relevant here.)

And in C89/C90, that special-case rule had not yet been added, so the behavior of &*x is undefined if x is a null (or otherwise invalid) pointer. Most pre-C99 compilers would probably optimize away the * and & anyway; remember, it's the nature of undefined behavior that something can behave just as you might expect it to behave.

On the other hand, there's a very real difference in the behavior of anyone reading the code. If I see y = x;, my behavior is to think "Oh, it's an ordinary pointer assignment." If I see y = &*x;, my behavior is to think "Why the heck did you write it that way?", and to change it to y = x; if I'm in a position to do so.

3
дададзена
Вялікі адказ. І, выкарыстоўваючы у = & * х з'яўляецца вельмі добрым (і бяспечны) спосаб сказаць: «. Гэй, я пачатковец, так што я не ведаю, што я раблю Дзейнічайце з асцярогай»
дададзена аўтар Elazar, крыніца

Яны альбо сапраўды гэтак жа, па вызначэнні, ці амаль тое ж самае, у залежнасці ад таго, якой версіі стандарту C вы маеце справу з.

У ISO C99 і C11, мы маем наступную фармулёўку (са спасылкай на N1570 C11 праект) у 6.5.3.2:

The unary & operator yields the address of its operand. If the operand has type "type", the result has type "pointer to type". If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.

Таму, улічваючы:

int *x = /* whatever */;
int *y;

гэтыя два дакладна эквівалентныя, , нават калі х пусты паказальнік :

y = x;
y = &*x;

Without the special-case rule, the behavior would be undefined, because the behavior of the * operator is defined only if its operand is a valid non-null pointer. But since the * is never evaluated, it has no behavior here, defined or otherwise. (The fact that, unlike x, &*x is not an lvalue is not relevant here.)

And in C89/C90, that special-case rule had not yet been added, so the behavior of &*x is undefined if x is a null (or otherwise invalid) pointer. Most pre-C99 compilers would probably optimize away the * and & anyway; remember, it's the nature of undefined behavior that something can behave just as you might expect it to behave.

On the other hand, there's a very real difference in the behavior of anyone reading the code. If I see y = x;, my behavior is to think "Oh, it's an ordinary pointer assignment." If I see y = &*x;, my behavior is to think "Why the heck did you write it that way?", and to change it to y = x; if I'm in a position to do so.

3
дададзена
Вялікі адказ. І, выкарыстоўваючы у = & * х з'яўляецца вельмі добрым (і бяспечны) спосаб сказаць: «. Гэй, я пачатковец, так што я не ведаю, што я раблю Дзейнічайце з асцярогай»
дададзена аўтар Elazar, крыніца

Так, яны такія ж, але вельмі заблытаная.

Вы можаце праверыць гэта, выканаўшы наступныя дзеянні:

y = &(*x);
printf("%p\n", (void*)x);
printf("%p\n", (void*)y);
2
дададзена
Тым не менш UB. <�Код>% р патрабуе аргумент тыпу несапраўдным * , а не Int * . Закіньце аргумент пустаце * , каб пазбегнуць UB. (Але гэта яшчэ не даказвае, што паводзіны вызначаюцца, ні адзін эксперымент не можа зрабіць гэта.)
дададзена аўтар Keith Thompson, крыніца
@Elazar: Там няма ніякай гарантыі, што несапраўдным * і Int * маюць такое ж уяўленне, ці нават калі яны робяць, што яны перадаюцца ў якасці аргументаў Printf такім жа чынам. Гэта, хутчэй за ўсё, працаваць на пераважнай большасці рэальных сістэм, але гэта не гарантуецца.
дададзена аўтар Keith Thompson, крыніца
На самай справе, друк зменнай з няслушнай радком фармату з'яўляецца UB (7.21.6.1 P9), так што тэст не паказвае нічога. Цяпер, калі вы зменіце тыя, % р , то мы гаворым. ;)
дададзена аўтар Mike, крыніца
@KeithThompson Як гэта можа зрабіць розніцу? І чаму?
дададзена аўтар Elazar, крыніца
Так, але гаворка ішла аб мове C, а не аб рэалізацыі C.
дададзена аўтар Elazar, крыніца
Гэты тэст не кажа шмат. Гэта можа толькі здарыцца так.
дададзена аўтар Elazar, крыніца
Лол, фіксаваныя, дзякуй :).
дададзена аўтар Geoffrey, крыніца
Друкавацца паказальнік адрас X & Y будзе адпавядаць, кажа само за сябе.
дададзена аўтар Geoffrey, крыніца

Так, яны такія ж, але вельмі заблытаная.

Вы можаце праверыць гэта, выканаўшы наступныя дзеянні:

y = &(*x);
printf("%p\n", (void*)x);
printf("%p\n", (void*)y);
2
дададзена
Тым не менш UB. <�Код>% р патрабуе аргумент тыпу несапраўдным * , а не Int * . Закіньце аргумент пустаце * , каб пазбегнуць UB. (Але гэта яшчэ не даказвае, што паводзіны вызначаюцца, ні адзін эксперымент не можа зрабіць гэта.)
дададзена аўтар Keith Thompson, крыніца
@Elazar: Там няма ніякай гарантыі, што несапраўдным * і Int * маюць такое ж уяўленне, ці нават калі яны робяць, што яны перадаюцца ў якасці аргументаў Printf такім жа чынам. Гэта, хутчэй за ўсё, працаваць на пераважнай большасці рэальных сістэм, але гэта не гарантуецца.
дададзена аўтар Keith Thompson, крыніца
На самай справе, друк зменнай з няслушнай радком фармату з'яўляецца UB (7.21.6.1 P9), так што тэст не паказвае нічога. Цяпер, калі вы зменіце тыя, % р , то мы гаворым. ;)
дададзена аўтар Mike, крыніца
@KeithThompson Як гэта можа зрабіць розніцу? І чаму?
дададзена аўтар Elazar, крыніца
Гэты тэст не кажа шмат. Гэта можа толькі здарыцца так.
дададзена аўтар Elazar, крыніца
Так, але гаворка ішла аб мове C, а не аб рэалізацыі C.
дададзена аўтар Elazar, крыніца
Лол, фіксаваныя, дзякуй :).
дададзена аўтар Geoffrey, крыніца
Друкавацца паказальнік адрас X & Y будзе адпавядаць, кажа само за сябе.
дададзена аўтар Geoffrey, крыніца

Так, хоць другая выглядае як запіс для конкурсу заблытвання.

2
дададзена

Вось зручная маленькая функцыя, якая можа дапамагчы. Не ўпэўнены, што вам трэба ўсё «ўключае ў сябе».

#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
int *x = (int *)malloc(sizeof(int));
int *y = x;
int *z = &*x;

//y = x;
//z = &*x;

 cout   << "x has type: " << typeid(x).name() << '\n'
        << "y has type: " << typeid(y).name() << '\n'
        << "z has type: " << typeid(z).name() << '\n'
        << "values are " << x <<"  "<< y << "  " << z  << '\n'; 
}

У выніку я атрымліваю ад гэтага:

x has type: Pi
y has type: Pi
z has type: Pi
values are 0x1a3a010  0x1a3a010  0x1a3a010

Адказ тады, так, метады сапраўды гэтак жа, з дапамогай Ubuntu 14.10, г ++

1
дададзена
Не маглі б вы дадаць выснова?
дададзена аўтар rapvelopment, крыніца

Вось зручная маленькая функцыя, якая можа дапамагчы. Не ўпэўнены, што вам трэба ўсё «ўключае ў сябе».

#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
int *x = (int *)malloc(sizeof(int));
int *y = x;
int *z = &*x;

//y = x;
//z = &*x;

 cout   << "x has type: " << typeid(x).name() << '\n'
        << "y has type: " << typeid(y).name() << '\n'
        << "z has type: " << typeid(z).name() << '\n'
        << "values are " << x <<"  "<< y << "  " << z  << '\n'; 
}

У выніку я атрымліваю ад гэтага:

x has type: Pi
y has type: Pi
z has type: Pi
values are 0x1a3a010  0x1a3a010  0x1a3a010

Адказ тады, так, метады сапраўды гэтак жа, з дапамогай Ubuntu 14.10, г ++

1
дададзена
Не маглі б вы дадаць выснова?
дададзена аўтар rapvelopment, крыніца

Наколькі мне вядома, яны дакладна эквівалентныя. Я буду здзіўлены, калі некаторыя кампілятар ставіцца да іх па-рознаму.

Because of presense of &, *x will not be evaluated at all. Hence even if x is null, it will not cause crash/seg-fault. (You can best verify using assembly.)

When we talk of assembly, it's impossible to calculate *x (value) & then &(*x) (pointer). Hence, compiler will simply calculate the address of *x, without calculating value of *x.

We can also check for more complex cases, like &(a[10]) It simply translates to a+10*sizeof(a[0]) in assembly.

Яшчэ адзін доказ было б offsetof Макрас, як правіла, вызначаецца як:

#define offsetof(st, m) ((size_t)(&((st *)0)->m))

Here, it's calculating &(null_pointer->m), which does not cause a crash.

1
дададзена
Добры пытанне, хоць на самай справе не з'яўляецца доказам.
дададзена аўтар Elazar, крыніца
BTW SizeOf не злічыць. <�Код> SizeOf (Е ( "% d", * (* лятучы INT) 0)) прывядзе да 4 ці 8, без якіх-небудзь пабочных эфектаў.
дададзена аўтар Elazar, крыніца
ды, SizeOf разглядае дадзеныя толькі тып даных, не якія ляжаць у аснове.
дададзена аўтар anishsane, крыніца

Наколькі мне вядома, яны дакладна эквівалентныя. Я буду здзіўлены, калі некаторыя кампілятар ставіцца да іх па-рознаму.

Because of presense of &, *x will not be evaluated at all. Hence even if x is null, it will not cause crash/seg-fault. (You can best verify using assembly.)

When we talk of assembly, it's impossible to calculate *x (value) & then &(*x) (pointer). Hence, compiler will simply calculate the address of *x, without calculating value of *x.

We can also check for more complex cases, like &(a[10]) It simply translates to a+10*sizeof(a[0]) in assembly.

Яшчэ адзін доказ было б offsetof Макрас, як правіла, вызначаецца як:

#define offsetof(st, m) ((size_t)(&((st *)0)->m))

Here, it's calculating &(null_pointer->m), which does not cause a crash.

1
дададзена
Добры пытанне, хоць на самай справе не з'яўляецца доказам.
дададзена аўтар Elazar, крыніца
BTW SizeOf не злічыць. <�Код> SizeOf (Е ( "% d", * (* лятучы INT) 0)) прывядзе да 4 ці 8, без якіх-небудзь пабочных эфектаў.
дададзена аўтар Elazar, крыніца
ды, SizeOf разглядае дадзеныя толькі тып даных, не якія ляжаць у аснове.
дададзена аўтар anishsane, крыніца