LINUX.ORG.RU

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 ★★★★★
()
Ответ на: комментарий от Pi

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

realloc ★★★★
()
Ответ на: комментарий от realloc

Так интереснее:

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

Да, i=4 и это однозначно :-)

Shaman007 ★★★★★
()
Ответ на: комментарий от anonymous

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

human0id ★★★
()
Ответ на: комментарий от human0id

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

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

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

ananas ★★★★★
()
Ответ на: комментарий от human0id

>Но 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 ★★★★
()
Ответ на: комментарий от human0id

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

anonymous
()
Ответ на: комментарий от ananas

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

>для примера попробуй 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 ★★★
()
Ответ на: комментарий от Shaman007

и что даже модераторы на С не умеют программировать?

anonymous
()
Ответ на: комментарий от Shaman007

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

' 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 ★★★★
()
Ответ на: комментарий от WFrag

Да, судя по приложению С я не прав. Я считал, что должно быть так: 'i = ' i++'.

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