Linux-Bulgaria.ORG
навигация

 

начало

пощенски списък

архив на групата

семинари ...

документи

как да ...

 

 

Предишно писмо Следващо писмо Предишно по тема Следващо по тема По Дата По тема (thread)

Re: lug-bg: c/cpp incr/decr


  • Subject: Re: lug-bg: c/cpp incr/decr
  • From: George Danchev <danchev@xxxxxxxxx>
  • Date: Thu, 20 Jan 2005 23:15:53 +0200

On Wednesday 19 January 2005 13:31, Valeri Vladev wrote:

-кръц-

> Изразите се парсват като трябва. Проблема е другаде.
> Накарах компилатора да ми изкара асемблирския код и всичко стана
> ясно.
> gcc version 3.3.4 (Debian 1:3.3.4-6sarge1)
> gcc -S 1.c
>
> #include <stdio.h>
> int
> main (void)
> {
> register int x = 0;
> register int a = 0;
>     x = x++ + (++x + a);
>     printf("(x = x++ + ++x) x = %d\n",x);
>     x = 0;
>     a = x++ + ++x;
>     printf("(a = x++ + ++x) a = %d\n",a);
>     printf("x = %d\n",x);
>     return (0);
> }
> Сложих още една променлива "а" за да го объркам малко.
> Иначе такъв код прави, че аз се обърквам.
> Изчислява израза от дясно на ляво, но:
>
>
>                 x = x++ + (++x + a);
> movl    $0, -4(%ebp)    ;х = 0
> movl    $0, -8(%ebp)    ;а = 0
> incl    -4(%ebp)        ;изчислява ++х
> movl    -4(%ebp), %edx  ;х вече 1 отива в edx
> addl    -8(%ebp), %edx  ;прибавя "а" към edx, edx = (++x + a) = 1
> movl    -4(%ebp), %eax  ;х отива в eax = 1
> addl    %edx, %eax      ;прибавя edx = (++x + a) = 1 към eax = x = 1
>                         ;eax = 2 което е и верния отговор
>                         ;сега би трябвало да си довърши работата х++
>                         ;и тогава да присвои резултата eax на х но!
> movl    %eax, -4(%ebp)  ;резултата се присвоява на х, x = 2
> incl    -4(%ebp)        ;и тогава се изпълнява х++ , x = 3

всичко това е много хубаво ;-) , но аз бих те попитал защо след като смяташ 
x = x++ + (++x + a); или x = x++ + ++x; (все тая) и a=x=0; 

и имаш x++ (в дясната страна) тогава резултата след завършване на израза не е 
ти се получава 1 ? Аз ще отчета само x++ (че е инкремент на x след израза) и 
съм готов с отговора ;-) няма защо да натрупвам резултата от сметките... (za 
tfa компила с -Wall казва недефинирано поведение с което ще се съгласят и в 
древна Елада ;-)

напиши го като a = b++ + ++c, дай им нули на всичките и ще получиш единица 
както и да го смяташ ;-) , т.е. в резултата от израза участва само един 
инкремент.

Ето още един лек пример:
*уж викаме еф с два аргумента i, но формалните параметри разделят разботата в 
две променливи, джам ;-)
*на пръв поглед всичко е ток и жица, но в последния printf израза не е 
завършен че да покажем стойностите на p и q без значение в къф ред ще 
събираме, ръгаме в скоби и т.н) - няма какво да принтираме и за трите 
%d-та...
*преди предпоследния printf израза е завършен и е ясно какво ще принтиме. 

#include <stdio.h>

void f(int p, int q );

int main(void)
{
   int i=0;
   printf("that's not a i++ + ++i collision\n");
   f(i, i);
   return 0;
}

void f(int p, int q)
{
   int a=0 ;
   p = 3 ;
   q = 4 ;

/* tfa e ok */
   printf("p++ + ++q = %d\n", p++ + ++q );
   printf("p = %d, %d\n", p, q );

/* tfa e ok */
   printf("p++ + ++q = %d\n", p++ + ++q );

/* tfa e ok */
   a = p++ + ++q;
   printf("p++ + ++q = %d\n, p = %d\n, q = %d\n", a , p, q );

/* tfa e undefined, dont try that at home! */
   printf("p = %d\n, q = %d\n, p++ + ++q = %d\n", p, q, p++ + ++q );
}


> Проблима е, че ползва за променливата от ляво и това което изчислява
> дясно една и съща памет! Сигурно е някаква оптимизация защото
> променливата е една и съща.

няма как компилатора да използва временна променлива за стойност която искаш 
хем да участва преди да е инкрементирана в израза, хем след като е 
инкрементирана да участва в израза и накрая този резултат да не противоречи 
на следствието от пост-инкрементирането (x++, което участва в израза). Това е 
математически невъзможно/недефинирано ;-)

> Ако при изчисляването на израза се използва временна променлива
> всичко щеше да е ОК.
> Такъв израз "x = x++ + ++x" нямам представа кой би си помислил да
> използва 

в този точно вид не (x = x++ + ++x), но може инцидентно да достигнеш до такова 
животно (без да искаш;) ... А иначе c = a++ + ++b е окай отсекъде, което може 
би се е имало в предвид. Т.е. с един израз да получим 
сбора от двете плюс единица (a+b+1) и всяко поотделно увеличено е единица (a+1 
и b+1 ... да се пишат 3 израза е грубо ;-) 
(Да, онова за въжето го знаем ;-) 

> но ако е семантично верен трябва да дава верен резултат. 

Семантично е неверен (виж горе)
т.е., след операция от вида x = x++ + ++ x, кое ще е стойността на x, това 
което се е натрупало от изчислението или просто следствието от x++ което е x 
+1 след изчисляване на израза, да но след изчислението на израза имаме друго 
натрупване като резултат.... Та не мой така механично да се счита ;-)

-- 
pub 4096R/0E4BD0AB 2003-03-18 <danchev.fccf.net/key pgp.mit.edu>
fingerprint    1AE7 7C66 0A26 5BFF DF22 5D55 1C57 0C89 0E4B D0AB 
============================================================================
A mail-list of Linux Users Group - Bulgaria (bulgarian linuxers).
http://www.linux-bulgaria.org - Hosted by Internet Group Ltd. - Stara Zagora
To unsubscribe: http://www.linux-bulgaria.org/public/mail_list.html
============================================================================


  • Във връзка с:

 

наши приятели

 

линукс за българи
http://linux-bg.org

FSA-BG
http://fsa-bg.org

OpenFest
http://openfest.org

FreeBSD BG
http://bg-freebsd.org

KDE-BG
http://kde.fsa-bg.org/

Gnome-BG
http://gnome.cult.bg/

проект OpenFMI
http://openfmi.net

NetField Forum
http://netField.ludost.net/forum/

 

 

Linux-Bulgaria.ORG

Mailing list messages are © Copyright their authors.