<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=4&amp;t=8075&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-08-10T09:29:33+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=8075&amp;mode</id>
<entry>
<author><name><![CDATA[Federerer]]></name></author>
<updated>2014-08-10T09:29:33+01:00</updated>
<published>2014-08-10T09:29:33+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90898#p90898</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90898#p90898"/>
<title type="html"><![CDATA[Re: zmienna zwracana przez funkcję]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90898#p90898"><![CDATA[
Tak właśnie robię, byłem ciekaw czy można inaczej do tego podejść.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4440">Federerer</a> — 10 sie 2014, o 09:29</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[atmel]]></name></author>
<updated>2014-08-09T22:07:24+01:00</updated>
<published>2014-08-09T22:07:24+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90872#p90872</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90872#p90872"/>
<title type="html"><![CDATA[Re: zmienna zwracana przez funkcję]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90872#p90872"><![CDATA[
Nie wiem czy dobrze myślę, ale jest też na to inny sposób, prócz statycznych tablic oczywiście.<br /><br />Można utworzyć wskaźnik w obszarze zmiennych globalnych na pewne miejsce w pamięci (zaalokować wstępnie 1 bajt pamięci dla uzyskania adresu). Następnie we własnej funkcji można użyć funkcji &quot;realloc&quot;, która powiększy ten obszar pamięci o konkretną wartość. Dzięki temu uzyskujemy poprawne wskazanie oraz niezmienne dane niezależne od miejsca ich lokowania. Zwracany wskaźnik w tym przypadku będzie poprawny i myślę, że ma to szanse działać <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Zamieszczam przykładowy kod:<br />[syntax=c]uint8_t * wsk = (uint8_t*)malloc(1);<br />uint8_t Index = 0;<br /> <br />uint8_t fun1(void) {<br /> <br />wsk = (uint8_t*)realloc(wsk, strlen((char*)wsk) + 2);<br />wsk&#91;strlen((char*)wsk) - 1&#93; = 16;<br />        return wsk&#91;strlen((char*)wsk) - 1&#93;;<br /> // Funkcja rozszerza obszar pamięci o 1 bajt, zapisuje do niego wartość 16, a następnie zwraca tę wartość<br />}<br /><br />uint8_t *fun2(void) {<br /> <br />wsk = (uint8_t*)realloc(wsk, strlen((char*)wsk) + 2);<br />wsk&#91;strlen((char*)wsk) - 1&#93; = 16;<br />        return wsk + strlen((char*)wsk) - 1;<br /> // Funkcja rozszerza obszar pamięci o 1 bajt, zapisuje do niego wartość 16, a następnie zwraca wskaźnik na tę wartość<br />}<br /><br />uint8_t *fun3(void) {<br /> <br />wsk = (uint8_t*)realloc(wsk, Index + 2);<br />wsk&#91;Index&#93; = 16;<br />        return wsk + Index++;<br /> // Funkcja rozszerza obszar pamięci o 1 bajt, zapisuje do niego wartość 16, a następnie zwraca wskaźnik na tę wartość<br />}<br /> <br /> <br />int main (void) {<br />       <br />        uint8_t z1 = fun1();// z1 == 16<br /><br />        uint8_t * z2 = fun2();// &amp;z2 == &amp;wsk&#91;0&#93;<br />        uint8_t * z3 = fun2();// &amp;z3 == &amp;wsk&#91;1&#93; itd.<br /><br />        uint8_t * z4 = fun3();// &amp;z4 == &amp;wsk&#91;0&#93;<br />       <br />}[/syntax]<br />Można zmodyfikować funkcje tak, aby mogły pobierać jako parametr dowolny adres w pamięci (może być to również zmienna lokalna dla funkcji &quot;main&quot;), a następnie powiększać go o 1 bajt. Zakładam tutaj że funkcja &quot;malloc&quot; oraz &quot;realloc&quot; automatycznie zeruje nowoutworzone komórki pamięci. W przeciwnym razie trzeba im przypisać wartość 0, albo użyć funkcji &quot;memset&quot; dla większych bloków alokowanej pamięci.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1183">atmel</a> — 9 sie 2014, o 22:07</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Federerer]]></name></author>
<updated>2014-08-09T21:56:42+01:00</updated>
<published>2014-08-09T21:56:42+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90871#p90871</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90871#p90871"/>
<title type="html"><![CDATA[Re: zmienna zwracana przez funkcję]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90871#p90871"><![CDATA[
Czyli tak jak myślałem. Można to jakoś zrobić bez użycia malloca i zwracania wskaźnika? Chodzi o to żeby funkcja tworzyła zmienną i jednocześnie zapisywała gdzieś wskaźnik do niej.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4440">Federerer</a> — 9 sie 2014, o 21:56</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[atmel]]></name></author>
<updated>2014-08-09T21:57:29+01:00</updated>
<published>2014-08-09T21:50:56+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90870#p90870</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90870#p90870"/>
<title type="html"><![CDATA[Re: zmienna zwracana przez funkcję]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90870#p90870"><![CDATA[
Tworząc taką zmienną w funkcji to tylko w jej zasięgu będzie ona widoczna. Zwracanie wskaźnika na taką zmienną może dać nieoczekiwane rezultaty przy jego wykorzystaniu, ponieważ po utraceniu zasięgu jest ona niszczona i jako już wolna komórka pamięci może ona zostać użyta przez program w dowolny sposób. Wobec czego bez Twojej wiedzy wartość 16 może ulec zmianie...<br /><br />Co to pytania czy &quot;y == wsk&quot; to odpowiedź brzmi &quot;nie&quot;. Dlatego że do zmiennej wskaźnikowej &quot;y&quot; zapisywany jest adres zmiennej &quot;z&quot; a nie &quot;x&quot;. Funkcja musiałaby zwracać wskaźnik na &quot;x&quot;, co jest zdecydowanie nie wskazane.<br /><br />Rozwiązaniem tych problemów w C++ są referencje, ale i w C można sobie całkiem nieźle poradzić używając wskaźników tzn. w głównej funkcji &quot;main&quot; alokowana jest pamięć, która nie zostanie nigdy automatycznie zwolniona, a następnie adres tego miejsca w pamięci przekazywany jest do funkcji, która ma na tych komórkach dokonywać operacji. Tym sposobem wskazanie jest cały czas poprawne (w przypadku tworzenia zmiennych na stosie, adres również jest poprawny, ale dane mogą ulec zmianie) oraz dane pozostają niezmienne (stos nie ma wpływu na młodsze adresowo komórki RAM.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1183">atmel</a> — 9 sie 2014, o 21:50</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Federerer]]></name></author>
<updated>2014-08-09T21:38:57+01:00</updated>
<published>2014-08-09T21:38:57+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90867#p90867</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90867#p90867"/>
<title type="html"><![CDATA[zmienna zwracana przez funkcję]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8075&amp;p=90867#p90867"><![CDATA[
Dajmy na to, że mam taki kod:<br /><br />[syntax=c]uint8_t * wsk;<br /><br />uint8_t fun(void) {<br /><br />uint8_t x = 16;<br />wsk = &amp;x;<br />return x;<br /><br />}<br /><br /><br />int main (void) {<br /><br />uint8_t z = fun();<br /><br />uint8_t * y = &amp;z;<br /><br />}[/syntax]<br /><br />Pytanie brzmi: czy y == wsk? Chodzi o to, czy wartość zwracana przez funkcję (czyli moje x, lokalne) jest tą samą komórką w pamięci co zmienna do której wrzucam wynik, czyli z.<br /><br />Po co mi to? Załóżmy, że w funkcji tworzę sobie jakąś zmienną, tworzę wskaźnik na nią i chcę go zapisać w jakiejś globalnej tablicy wskaźników a następnie ją zwrócić i móc potem ją odczytywać korzystając z mojej tablicy ze wskaźnikami. Wiem, że można użyć malloc i zwracać wskaźnik, ale jestem ciekaw jak są zwracane wartości przez funkcję. Podejrzałem kod assemblera wygenerowany z tego przykładu, ale jestem za cienki w asm żeby odpowiedzieć sobie samemu. Wygląda to tak:<br /><br />[syntax=asm]uint8_t * wsk;<br /><br />uint8_t fun(void) {<br />  7c:cf 93       pushr28<br />  7e:df 93       pushr29<br />  80:1f 92       pushr1<br />  82:cd b7       inr28, 0x3d; 61<br />  84:de b7       inr29, 0x3e; 62<br /><br />uint8_t x = 16;<br />  86:80 e1       ldir24, 0x10; 16<br />  88:89 83       stdY+1, r24; 0x01<br />wsk = &amp;x;<br />  8a:ce 01       movwr24, r28<br />  8c:01 96       adiwr24, 0x01; 1<br />  8e:90 93 61 00 sts0x0061, r25<br />  92:80 93 60 00 sts0x0060, r24<br />return x;<br />  96:89 81       lddr24, Y+1; 0x01<br /><br />}<br />  98:0f 90       popr0<br />  9a:df 91       popr29<br />  9c:cf 91       popr28<br />  9e:08 95       ret<br /><br />000000a0 &lt;main&gt;:<br /><br /><br />int main (void) {<br />  a0:cf 93       pushr28<br />  a2:df 93       pushr29<br />  a4:00 d0       rcall.+0      ; 0xa6 &lt;main+0x6&gt;<br />  a6:1f 92       pushr1<br />  a8:cd b7       inr28, 0x3d; 61<br />  aa:de b7       inr29, 0x3e; 62<br /><br />uint8_t t = fun();<br />  ac:0e 94 3e 00 call0x7c; 0x7c &lt;fun&gt;<br />  b0:8b 83       stdY+3, r24; 0x03<br /><br />uint8_t * y = &amp;t;<br />  b2:ce 01       movwr24, r28<br />  b4:03 96       adiwr24, 0x03; 3<br />  b6:9a 83       stdY+2, r25; 0x02<br />  b8:89 83       stdY+1, r24; 0x01<br /><br />while(1) {<br /><br /><br /><br />}<br />  ba:ff cf       rjmp.-2      ; 0xba &lt;main+0x1a&gt;[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4440">Federerer</a> — 9 sie 2014, o 21:38</p><hr />
]]></content>
</entry>
</feed>