LINUX.ORG.RU

Ответ на: Re: Потестируем инкремент! от mikhail

Re: Потестируем инкремент!

mikhail, не скомпилируется? Нарушение спецификаций языка? Не скрывай, чего у тебя получилось?

Tsahes ()

Re: Потестируем инкремент!

Умничаем? =) Это ж самые основы.

Вот я тоже поумничаю. Я выпустил оптимизирующий патч для твоей программы:

--- prog.c 2005-02-22 14:47:34.000000000 +0200
+++ test.c 2005-02-22 14:46:47.000000000 +0200
@@ -1,4 +1,3 @@
-#include <stdio.h>
int main (int argc, unsigned char **argv) {
int i = 0;
i = i++;

Selecter ★★★★ ()

Re: Потестируем инкремент!

0

И это неудивительно, ибо результат операции i++ есть значение i до инкремента.

human0id ★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

> И это неудивительно, ибо результат операции i++ есть значение i до инкремента.

сам понял, что сказал?

ananas ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

> 0

> И это неудивительно, ибо результат операции i++ есть значение i до инкремента.

С какого бодуна, ++ выполнится после присвоения.

anonymous ()
Ответ на: Re: Потестируем инкремент! от anonymous

Re: Потестируем инкремент!

Вы мой идеал. Всегда завидовал людям, которые на это способны. Да, а еще я один раз видел человека, который оценивал программу, глядя на ее байт-код.

Tsahes ()
Ответ на: Re: Потестируем инкремент! от anonymous

Re: Потестируем инкремент!

>> 0

>> И это неудивительно, ибо результат операции i++ есть значение i до инкремента.

>С какого бодуна, ++ выполнится после присвоения. 


	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	andl	$-16, %esp
	movl	$0, %eax
	subl	%eax, %esp
	movl	$0, -4(%ebp)
	movl	-4(%ebp), %edx
	leal	-4(%ebp), %eax
	incl	(%eax)              ; инкремент
	movl	%edx, -4(%ebp)      ; присвоение
	movl	-4(%ebp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC0, (%esp)
	call	printf
	movl	$0, %eax
	leave
	ret

human0id ★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

> movl %edx, -4(%ebp) ; присвоение

это - не присвоение. убери в сишном коде аргументы main-а - увидишь.

ananas ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

>       incl    (%eax)              ; инкремент
>       movl    %edx, -4(%ebp)      ; присвоение
>       movl    -4(%ebp), %eax

что-то непохоже на присвоение, аккамулятор вообще перетёрли

anonymous ()

Re: Потестируем инкремент!

inkrement - vpolne samostojatel'naja edenica jazyka. ejo vypolnenie, vozvrashiaet znacenie, ko-e ravno 0, t.k., skazhem, oshibok ne proizoshlo. Navernoe eto tak objasniajetsia...

P.S. sorry za translit

Pi ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от Pi

Re: Потестируем инкремент!

В данном случае выражение (i++) возвращает значение до операции и присваивает переменной значение, полученное оператором ++ для её типа.

realloc ★★★★ ()

Re: Потестируем инкремент!

Undefined behaviour.

Между присваиванием и модификацией переменной нет точек следования (sequence point).

WFrag ★★★★ ()
Ответ на: Re: Потестируем инкремент! от anonymous

Re: Потестируем инкремент!

То что написал шаман (i+= i++ + ++i) действительно undefined behaviour. Но i = i++ вовсе не undefined, потому как вначале вычисляется i++ (его значением будет 0), а потом происходит присвоение. Почитайте что ли у Кернигана, что есть оператор присвоение в Си.

human0id ★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

> Но i = i++ вовсе не undefined, потому как вначале вычисляется i++ (его значением будет 0), а потом происходит присвоение

неправильно. вначале происходит присвоение, потом - инкремент.

для примера попробуй j = i++; и j = ++i; и сравни результаты.

ananas ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

>Но i = i++ вовсе не undefined, потому как вначале вычисляется i++ (его значением будет 0), а потом происходит присвоение.

Именно что undefined behaviour. По причинам, озвученным выше - между присваиванием и изменением значения переменной нет точек следования. Что по определению является undefined behaviour.

>Почитайте что ли у Кернигана, что есть оператор присвоение в Си.

Какого года книжка? Которая старая, что-ли? Или я от жизни отстал? :)

Насколько я помню, эта "фича" (точки следования) появилась относительно недавно (в стандарте C99?), точно не уверен. Может была и раньше, не знаю. Но факт в том, что она точно есть :)

Цитата:

3.3: What should the code "int i = 3; i = i++;" do?

A: The expression is undefined.

Источник: http://www.cs.uu.nl/wais/html/na-dir/C-faq/abridged.html

WFrag ★★★★ ()
Ответ на: Re: Потестируем инкремент! от human0id

Re: Потестируем инкремент!

i++ - постинкрементация выполняется после вычисления выражения.

anonymous ()
Ответ на: Re: Потестируем инкремент! от ananas

Re: Потестируем инкремент!

>неправильно. вначале происходит присвоение, потом - инкремент.

>для примера попробуй j = i++; и j = ++i; и сравни результаты. 


=========== inc1.c ================
#include <stdio.h>

int main()
{
    int i = 0;
    int j;
    i = i++;
    printf("%d\n", i);
    return 0;
}
===================================

=========== inc2.c ================
#include <stdio.h>

int main()
{
    int i = 0;
    int j;
    j = i++;
    printf("%d\n", i);
    return 0;
}
==================================

$ gcc -S inc1.c inc2.c
$ vimdiff inc1.s vim2.s

======= inc1.s ================================= inc2.s =====================
        andl    $-16, %esp              |        andl    $-16, %esp
        movl    $0, %eax                |        movl    $0, %eax
        subl    %eax, %esp              |        subl    %eax, %esp
        movl    $0, -4(%ebp)            |        movl    $0, -4(%ebp)
        movl    -4(%ebp), %edx          |        movl    -4(%ebp), %edx
        leal    -4(%ebp), %eax          |        leal    -4(%ebp), %eax
        incl    (%eax)                  |        incl    (%eax)
!!!     movl    %edx, -4(%ebp)          |        movl    %edx, -8(%ebp)      !!!   
        movl    -4(%ebp), %eax          |        movl    -4(%ebp), %eax
        movl    %eax, 4(%esp)           |        movl    %eax, 4(%esp)
        movl    $.LC0, (%esp)           |        movl    $.LC0, (%esp)
        call    printf                  |        call    printf
        movl    $0, %eax                |        movl    $0, %eax
        leave                           |        leave
        ret                             |        ret
=======================================================================

Как видно, присвоение выполняется _после_ инкремента.

$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-linux/3.3.4/specs
Configured with: ../src/configure -v --enable-languages=c,c++,java,f77,pascal,objc,ada,treelang --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.3 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enable-debug --enable-java-gc=boehm --enable-java-awt=xlib --enable-objc-gc i486-linux
Thread model: posix
gcc version 3.3.4 (Debian 1:3.3.4-2)

human0id ★★★ ()

Re: Потестируем инкремент!

Вопрос ко всем гуру, если можно. Где можно почитать про синтаксис асма в Unix? В частности, что означают числа и скобки вокруг операндов, например как в "movl -4(%ebp), %edx" и что означает буква l в конце мнемоник команд? Заранее спасибо за ответы.

anonymous ()

Re: Потестируем инкремент!

ну ноль получится, и что из этого?
не понимаю зачем такие конструкции писать.
какие выгоды это дает?

anonymous ()
Ответ на: Re: Потестируем инкремент! от anonymous

Re: Потестируем инкремент!

"movl -4(%ebp), %edx" Копировать из адреса который в регистре ebp минус 4 байта в регистр edx l значит лонг 32бит.

Есть книжка Programming from the ground up. Jonathan Bartlett для начала весьма подходящая.

SatanClaus ★★★ ()

Re: Потестируем инкремент!

$ cat 1.c
#include <stdio.h>
int main (int argc, unsigned char **argv) {
  int i = 0;
  i = i++;
  printf ("i = %d\n", i);
  return 0;
}

$ ./a.exe
i = 1

$ gcc -v
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.3.1/specs
Configured with: /GCC/gcc-3.3.1-3/configure --with-gcc --with-gnu-ld --with-gnu-
as --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --libexe
cdir=/usr/sbin --mandir=/usr/share/man --infodir=/usr/share/info --enable-langua
ges=c,ada,c++,f77,pascal,java,objc --enable-libgcj --enable-threads=posix --with
-system-zlib --enable-nls --without-included-gettext --enable-interpreter --enab
le-sjlj-exceptions --disable-version-specific-runtime-libs --enable-shared --dis
able-win32-registry --enable-java-gc=boehm --disable-hash-synchronization --verb
ose --target=i686-pc-cygwin --host=i686-pc-cygwin --build=i686-pc-cygwin
Thread model: posix
gcc version 3.3.1 (cygming special)

Reset ★★★★★ ()

Re: Потестируем инкремент!

По-моему в любом FAQ по C, в конференции на C, обсуждался данный вопрос.

Ответ прост: поведение не определенно.

печально что оказывается так много людей не умееют программировать на языке
C.

linux_guru ()

Re: Потестируем инкремент!

C:\cygwin\home\manwe>gcc 1.c

C:\cygwin\home\manwe>a.exe
i = 0

C:\cygwin\home\manwe>gcc -v
Reading specs from c:/mingw/bin/../lib/gcc/mingw32/3.4.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=
mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable
-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --e
nable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-ja
va-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchroniz
ation --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.2 (mingw-special)

Reset ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от SatanClaus

Re: Потестируем инкремент!

>Есть книжка Programming from the ground up. Jonathan Bartlett для начала весьма подходящая.

а эту книга в электронном варианте нито не видел?

anonymous ()

Re: Потестируем инкремент!

C:\cygwin\home\manwe>cl 1.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

1.c
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:1.exe
1.obj

C:\cygwin\home\manwe>1.exe
i = 1

Reset ★★★★★ ()

Re: Потестируем инкремент!

C:\cygwin\home\manwe>icl 1.c -c
Intel(R) C++ Compiler for 32-bit applications, Version 8.1    Build 20040802Z Pa
ckage ID: W_CC_P_8.1.018
Copyright (C) 1985-2004 Intel Corporation.  All rights reserved.

1.c

C:\cygwin\home\manwe>xilink6 1.obj
xilink6: executing 'link'
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

1.obj

C:\cygwin\home\manwe>1.exe
i = 0

Reset ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от WFrag

Re: Потестируем инкремент!

Конечно зря! В том, что ты процитировал (п.п. 3.1)нет ссылки на стандарты ISO, ANSI или на конкретные реализации. Например, на этот: http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf

Shaman007 ★★★★★ ()
Ответ на: Re: Потестируем инкремент! от Shaman007

Re: Потестируем инкремент!

Учится не по стандарту надо. Он нужен исключительно для религиозных войн, как библия :)

' i = i++ '

' - точки следования.

Параграф 4/1, семантика "shall" / "shall not"

6.5/2 - между двумя точками следования значение переменной должно быть изменено лишь один раз.

6.5.2.4/2 - обновление значения переменной (операция ++) должно произойти до следующей точки следования.

6.5.16/3 - обновление значения переменной (операция присваивания) должно произойти до следующей точки следования.

Соответственно, имеем undefined behaviour - между двумя точками следования значение меняется два раза.

Обрати внимания на сноску 70 параграфа 6.5, подпункт 2. Там практически этот пример и приведен.

P.S. Ссылка на стандарт C99: http://www.nirvani.net/docs/ansi_c.pdf

WFrag ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.