ufm: (Default)
[personal profile] ufm
ufm@home ~ $ cat t.c
#include <stdio.h>

int main(void) {
int i;
volatile int j;

   i = j = 5;
   i = ++i + ++i;
   j = ++j + ++j;
   printf ("i == %d j == %d\n",i,j);

   i = j = 5;
   i = i++ + ++i;
   j = j++ + ++j;
   printf ("i == %d j == %d\n",i,j);

   i = j = 5;
   i = i++ + i++;
   j = j++ + j++;
   printf ("i == %d j == %d\n",i,j);

   i = j = 5;
   i = ++i + i++;
   j = ++j + j++;
   printf ("i == %d j == %d\n",i,j);

   return 0;
}

ufm@home ~ $ gcc t.c
ufm@home ~ $ ./a.out
i == 14 j == 13
i == 13 j == 11
i == 12 j == 10
i == 13 j == 12
ufm@home ~ $

(no subject)

Date: 2007-05-12 11:35 (UTC)
From: [identity profile] dil.livejournal.com
Это каждый дурак может :) Я даже не поленился посмотреть в ассемблерный код, который gcc делает.
Ты вот лучше объясни логику - почему в первом варианте для не-volatile переменной получается 14.

(no subject)

Date: 2007-05-12 12:24 (UTC)
From: [identity profile] galkao.livejournal.com
И мне тоже объясните, пожалуйста:-) 12 должно быть, казалось бы...

(no subject)

Date: 2007-05-12 12:26 (UTC)
From: [identity profile] galkao.livejournal.com
АААА! А в современном С знак "=" - это операция присвоения? А как же теперь тогда выглядит операция сравнения?

(no subject)

Date: 2007-05-12 12:44 (UTC)
From: [identity profile] dil.livejournal.com
Эм. Она отродясь была операцией присваивания. Сравнение - это ==

(no subject)

Date: 2007-05-12 12:51 (UTC)
From: [identity profile] galkao.livejournal.com
Это меня проглючило:-) сто лет не программировала:) Наверное, меня вид результата сбил с толку...

(no subject)

Date: 2007-05-12 12:42 (UTC)
From: [identity profile] dil.livejournal.com
С моей точки зрения - 13.
Инерементируем i, получается 6, берем это значение, потом еще раз инкрементируем i, получается 7, складываем 6 и 7, получается 13.

На деле, если оно не volatile, то оно сначала два раза инкрементируется, а потом уже результат сам с собой складывается, получается 14.
А почему так - я не понимаю.

(no subject)

Date: 2007-05-12 12:50 (UTC)
From: [identity profile] galkao.livejournal.com
Да, точно, 13 должно быть. Я забыла, что i уже изменилось к моменту последующей операции...

(no subject)

Date: 2007-05-12 19:40 (UTC)
From: [identity profile] blacklion.livejournal.com
приоритет операций. Префиксный ++ приоритетней бинарного +'а.

(no subject)

Date: 2007-05-12 20:05 (UTC)
From: [identity profile] dil.livejournal.com
И что? что сначала вычисляются оба инкремента, а потом происходит сложение, это понятно.
Непонятно, почему складывается дважды последнее значение i (7), а не то, которое было на момент после собственно инкремента (в одном случае 7, в другом 6).

А еще непонятнее, почему в случае volatile оно происходит по-другому.

(no subject)

Date: 2007-05-13 06:02 (UTC)
From: [identity profile] blacklion.livejournal.com
Понятно почему -- undefined beh. Все эти ++/--, Как префиксные так и инфиксные, здорово завязаны на sequence point. А внутри этого выражения его нет...

(no subject)

Date: 2007-05-13 06:04 (UTC)
From: [identity profile] blacklion.livejournal.com
И на другом компиляторе результат может быть другой. И даже при другой оптимизации он может быть другим:

i == 14 j == 14
i == 13 j == 13
i == 12 j == 12
i == 13 j == 13

Это cl.exe из VC 8 Epxress (Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86)

(no subject)

Date: 2007-05-13 07:13 (UTC)
From: [identity profile] blacklion.livejournal.com
Непонятно, почему складывается дважды последнее значение i (7), а не то, которое было на момент после собственно инкремента (в одном случае 7, в другом 6).
Вообще, по моим ощущениям тут должно быть так:

(1) Инкремент. Его результат -- 6. В i по-прежнему 5, так как сайд-эффект промоутится только на Sequence point, но мы помним, что надо записать 6 в i.
(2) Инкремент. Его результат -- 6. В i по-прежнему 5, так как сайд-эффект промоутится только на Sequence point, но мы помним, что надо записать 6 в i.
(3) Складываем 6 и 6, результат -- 12
(4) i = 12
(5) Конфликт срабатывания сайд-эффектов (1) и (2), то самое неопределённое поведение...

Как разрулится конфликт (Вплоть до инкрементирования i опять дважды) -- вопрос компилятора...

(no subject)

Date: 2007-05-12 11:40 (UTC)
From: [identity profile] separator829.livejournal.com
Имхо еще надо gcc -v показать...

(no subject)

Date: 2007-05-12 20:33 (UTC)
From: [identity profile] ufm.livejournal.com
ufm@home ~ $ gcc -v
Reading specs from /usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/specs
Configured with: /var/tmp/portage/sys-devel/gcc-3.4.6-r2/work/gcc-3.4.6/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/3.4.6 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/3.4.6 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/3.4.6/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/3.4.6/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-libunwind-exceptions --enable-multilib --disable-libgcj --enable-languages=c,c++ --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu
Thread model: posix
gcc version 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10)

(no subject)

Date: 2007-05-12 12:22 (UTC)
From: [identity profile] galkao.livejournal.com
Слушай, а я в С с таким никогда не сталкивалась: volatile int j
Что такое volatile? Либо я была невнимательна, либо в то время, когда я писала на С, такого не было.

(no subject)

Date: 2007-05-12 12:52 (UTC)
From: [identity profile] dil.livejournal.com
Это указание компилятору, что значение переменной может меняться асинхронно (например, по прерыванию), и что он не должен делать никаких предположений относительно ее значения в текущий момент, даже если сам в нее только что чего-нибудь положил.
Существует, кажется, со времен ANSI-стандарта, в K&R его, вроде бы, еще не было.

(no subject)

Date: 2007-05-12 13:12 (UTC)
From: [identity profile] galkao.livejournal.com
"в K&R его, вроде бы, еще не было." - вот я и смотрю, что незнакомое, я же как раз по K&R С изучала:-)

Это код - диагноз

Date: 2007-05-12 12:28 (UTC)
From: [identity profile] ono-it.livejournal.com
Дядя Федор, ты знаешь, что такой код писать нельзя ...

(no subject)

Date: 2007-05-12 12:44 (UTC)
From: [identity profile] elk.livejournal.com
Можно или нельзя, но компилятор облажался, конечно.

(no subject)

Date: 2007-05-12 15:59 (UTC)
From: [identity profile] uncle-asa.livejournal.com
Где? Я не вижу ни одного нарушения стандарта.

(no subject)

Date: 2007-05-13 01:41 (UTC)
From: [identity profile] elk.livejournal.com
Операции над int и volatile int могут различаться результатом?

(no subject)

Date: 2007-05-13 03:36 (UTC)
From: [identity profile] uncle-asa.livejournal.com
А почему нет? Порядок вычисления оставлен стандартом на совесть оптимизатора. Во всех книжках написано, что результат непредсказуем.

(no subject)

Date: 2007-05-13 15:37 (UTC)
From: [identity profile] generos.livejournal.com
Не до такой же степени! :-)

(no subject)

Date: 2007-05-13 15:40 (UTC)
From: [identity profile] uncle-asa.livejournal.com
Нефиг-нефиг! Программировать красиво учитесь ;)

А то потом народ спрашивает нафига я конструкции вида u = (*p++) | (*p++ << 8); из кода выкидываю и у меня почему-то всё работает, а у них нет ;)

(no subject)

Date: 2007-05-12 17:41 (UTC)
From: [identity profile] mike-gusev.livejournal.com
gusev@casa-babylon:[~/works/src/plusplus]$ ./pls
i == 14 j == 13
i == 13 j == 6
i == 12 j == 6
i == 13 j == 7
gusev@casa-babylon:[~/works/src/plusplus]$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
gusev@casa-babylon:[~/works/src/plusplus]$

(no subject)

Date: 2007-05-12 17:44 (UTC)
From: [identity profile] mike-gusev.livejournal.com
-Wall честно обругал каждую операцию:
pls.c:9: warning: operation on ‘i’ may be undefined
pls.c:9: warning: operation on ‘i’ may be undefined
pls.c:10: warning: operation on ‘j’ may be undefined
pls.c:10: warning: operation on ‘j’ may be undefined
итд...

(no subject)

Date: 2007-05-13 16:25 (UTC)
From: [identity profile] mike-gusev.livejournal.com
Завтра попробую bcc32, openwatcom и visual :-)

(no subject)

Date: 2007-05-12 20:28 (UTC)
From: [identity profile] ufm.livejournal.com
У меня 3.4.6

(no subject)

Date: 2007-05-13 15:35 (UTC)
From: [identity profile] generos.livejournal.com
Sun Studio более предсказуем:
%cc -v
cc: Sun C 5.9 Linux_i386 Build35_2 2006/12/04
usage: cc [ options] files. Use 'cc -flags' for details
% cc t.c && ./a.out
i == 14 j == 14
i == 13 j == 13
i == 12 j == 12
i == 13 j == 13

(no subject)

Date: 2007-05-13 18:35 (UTC)
From: [identity profile] mikell.livejournal.com
Безотносительно причин такого поведения компилятора - я в легком офигении. Впрочем, сам в код пишу максимум однострочные конструкции вида "i++;"...

(no subject)

Date: 2007-05-15 14:35 (UTC)
From: [identity profile] sdvn.livejournal.com
C# выдал на i = ++i + ++i;
13.