Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.58/12: Рейтинг темы: голосов - 12, средняя оценка - 4.58
Pershin
0 / 0 / 0
Регистрация: 15.07.2013
Сообщений: 14
1

Обмен переменных через XOR - тонкости

29.01.2014, 12:45. Просмотров 2507. Ответов 20
Метки нет (Все метки)

C
1
2
3
4
5
main()
{
    int a=5, b=10;
    a^=b; b^=a; a^=b; printf("%d %d", a, b);
}
C
1
2
3
4
5
main()
{
    int a=5, b=10;
    a^=b^=a^=b; printf("%d %d", a, b);
}
Оба этих кода работают. Википедия говорит, что вторая форма записи - плохо, это undefined behaviour, и может привести к ошибкам.
Но у меня это работало, и я успешно пользовался второй записью, как более короткой, в своих учебных программах.
Однако, как сегодня выяснилось, вторая запись перестает работать, если вынести обмен в функцию:
C
1
2
3
4
5
6
7
8
9
10
void swap(int *a, int *b)
{
    *a^=*b; *b^=*a; *a^=*b;
}
 
main()
{
    int a=5, b=10;
    swap(&a, &b); printf("%d %d", a, b);
}
C
1
2
3
4
5
6
7
8
9
10
void swap(int *a, int *b)
{
    *a^=*b^=*a^=*b;
}
 
main()
{
    int a=5, b=10;
    swap(&a, &b); printf("%d %d", a, b);
}
Первая форма записи работает, как и раньше, а вот вторая выводит числа 0 и 5 вместо 10 и 5.

Хотелось бы разобраться. Компилятор gcc 4.6.3.
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.01.2014, 12:45
Ответы с готовыми решениями:

Обмен переменных в языке С
Доброго времени суток! Помогите пожалуйста разобраться с заданием, я изучаю самостоятельно язык...

Тонкости сложных переменных в строках
По истине удивительные и, в то же время, странные вещи позволяет делать синтаксис сложных...

XOR для N переменных
Собственно сабж. Сделал так: function XORN() { a=0 for n in $(seq $#); do (( a = a +...

Тонкости парсинга через Fizzler и HtmlAgilityPack
Привет. Есть простой код для парсинга сайта на HtmlAgilityPack с поддержкой Fizzler. В целом все...

Обмен переменных string
Здравствуйте. Подскажите пожалуйста, как ПРАВИЛЬНО и КРАСИВО поменять местами две...

20
Boleon
Guardian of Asgaard
375 / 317 / 197
Регистрация: 11.11.2013
Сообщений: 1,046
Завершенные тесты: 1
29.01.2014, 13:05 2
Цитата Сообщение от Pershin Посмотреть сообщение
C
1
a^=b^=a^=b;
C
1
*a^=*b^=*a^=*b;
в этих случаях у меня даже не компилится, вылетает ошибка "operation on ‘a’ may be undefined"
0
Pershin
0 / 0 / 0
Регистрация: 15.07.2013
Сообщений: 14
29.01.2014, 13:08  [ТС] 3
У меня компилится и то и то, но правильно работает только первое.
Да, я понимаю, что глючит скорее всего из-за UB, но хочу понять, как именно глючит.

Кстати, такой код есть например здесь (пункт 4). Точно такой же, как у меня, Скобки ничего не решают (с ними я тоже пробовал). Получается, что и в статье некорректный код?
0
Charles Kludge
Клюг
7656 / 3171 / 383
Регистрация: 03.05.2011
Сообщений: 8,381
29.01.2014, 17:22 4
Хм, компилится и работает правильно и то, и другое.
Open Watcom C32 Optimizing Compiler Version 1.8
ЧЯДНТ?

Добавлено через 16 минут
А вот gcc version 4.2.1 20070719 [FreeBSD] даёт ошибочное 0 5.

Добавлено через 1 час 8 минут
И да, я не поленился проверить - древнейший трупоСю
Turbo C++ Version 3.00 Copyright (c) 1992 Borland International
и бугланд С++ Быдлер
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
тоже компилят и работает правильно и то, и другое.
К чему бы это?
0
vua72
418 / 417 / 167
Регистрация: 28.11.2010
Сообщений: 1,183
Завершенные тесты: 1
29.01.2014, 19:32 5
Лучший ответ Сообщение было отмечено Pershin как решение

Решение

Велосипед с квадратными колесами.
Но если так хочется разобраться, то
Первый код на ассемблере:
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
main_1.c      **** void swap(int *a, int *b)
   4:main_1.c      **** {
  10                    .loc 1 4 0
  11                    .cfi_startproc
  12 0000 55            push    rbp
  13                    .cfi_def_cfa_offset 16
  14                    .cfi_offset 6, -16
  15 0001 4889E5        mov rbp, rsp
  16                    .cfi_def_cfa_register 6
  17 0004 48897DF8      mov QWORD PTR [rbp-8], rdi
  18 0008 488975F0      mov QWORD PTR [rbp-16], rsi
   5:main_1.c      ****     *a^=*b;
  19                    .loc 1 5 0
  20 000c 488B45F8      mov rax, QWORD PTR [rbp-8]
  21 0010 8B10          mov edx, DWORD PTR [rax]
  22 0012 488B45F0      mov rax, QWORD PTR [rbp-16]
  23 0016 8B00          mov eax, DWORD PTR [rax]
  24 0018 31C2          xor edx, eax
  25 001a 488B45F8      mov rax, QWORD PTR [rbp-8]
  26 001e 8910          mov DWORD PTR [rax], edx
   6:main_1.c      ****     *b^=*a;
  27                    .loc 1 6 0
  28 0020 488B45F0      mov rax, QWORD PTR [rbp-16]
  29 0024 8B10          mov edx, DWORD PTR [rax]
  30 0026 488B45F8      mov rax, QWORD PTR [rbp-8]
  31 002a 8B00          mov eax, DWORD PTR [rax]
  32 002c 31C2          xor edx, eax
  33 002e 488B45F0      mov rax, QWORD PTR [rbp-16]
  34 0032 8910          mov DWORD PTR [rax], edx
   7:main_1.c      ****     *a^=*b;
  35                    .loc 1 7 0
  36 0034 488B45F8      mov rax, QWORD PTR [rbp-8]
  37 0038 8B10          mov edx, DWORD PTR [rax]
  38 003a 488B45F0      mov rax, QWORD PTR [rbp-16]
  39 003e 8B00          mov eax, DWORD PTR [rax]
  40 0040 31C2          xor edx, eax
  41 0042 488B45F8      mov rax, QWORD PTR [rbp-8]
  42 0046 8910          mov DWORD PTR [rax], edx
   8:main_1.c      ****     
   9:main_1.c      **** }

Второй:
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
:main.c        **** void swap(int *a, int *b)
   4:main.c        **** {
  10                    .loc 1 4 0
  11                    .cfi_startproc
  12 0000 55            push    rbp
  13                    .cfi_def_cfa_offset 16
  14                    .cfi_offset 6, -16
  15 0001 4889E5        mov rbp, rsp
  16                    .cfi_def_cfa_register 6
  17 0004 48897DF8      mov QWORD PTR [rbp-8], rdi
  18 0008 488975F0      mov QWORD PTR [rbp-16], rsi
   5:main.c        ****     *a^=*b^=*a^=*b;
  19                    .loc 1 5 0
  20 000c 488B45F8      mov rax, QWORD PTR [rbp-8]
  21 0010 8B10          mov edx, DWORD PTR [rax]
  22 0012 488B45F0      mov rax, QWORD PTR [rbp-16]
  23 0016 8B08          mov ecx, DWORD PTR [rax]
  24 0018 488B45F8      mov rax, QWORD PTR [rbp-8]
  25 001c 8B30          mov esi, DWORD PTR [rax]
  26 001e 488B45F0      mov rax, QWORD PTR [rbp-16]
  27 0022 8B00          mov eax, DWORD PTR [rax]
  28 0024 31C6          xor esi, eax
  29 0026 488B45F8      mov rax, QWORD PTR [rbp-8]
  30 002a 8930          mov DWORD PTR [rax], esi
  31 002c 488B45F8      mov rax, QWORD PTR [rbp-8]
  32 0030 8B00          mov eax, DWORD PTR [rax]
  33 0032 31C1          xor ecx, eax
  34 0034 488B45F0      mov rax, QWORD PTR [rbp-16]
  35 0038 8908          mov DWORD PTR [rax], ecx
  36 003a 488B45F0      mov rax, QWORD PTR [rbp-16]
  37 003e 8B00          mov eax, DWORD PTR [rax]
  38 0040 31C2          xor edx, eax
  39 0042 488B45F8      mov rax, QWORD PTR [rbp-8]
  40 0046 8910          mov DWORD PTR [rax], edx
   6:main.c        **** }

Нормальный swap
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 3:main2.c       **** void swap(int *a, int *b)
   4:main2.c       **** {
  10                    .loc 1 4 0
  11                    .cfi_startproc
  12 0000 55            push    rbp
  13                    .cfi_def_cfa_offset 16
  14                    .cfi_offset 6, -16
  15 0001 4889E5        mov rbp, rsp
  16                    .cfi_def_cfa_register 6
  17 0004 48897DE8      mov QWORD PTR [rbp-24], rdi
  18 0008 488975E0      mov QWORD PTR [rbp-32], rsi
   5:main2.c       ****     int t=*a;
  19                    .loc 1 5 0
  20 000c 488B45E8      mov rax, QWORD PTR [rbp-24]
  21 0010 8B00          mov eax, DWORD PTR [rax]
  22 0012 8945FC        mov DWORD PTR [rbp-4], eax
   6:main2.c       ****     *a=*b;
  23                    .loc 1 6 0
  24 0015 488B45E0      mov rax, QWORD PTR [rbp-32]
  25 0019 8B10          mov edx, DWORD PTR [rax]
  26 001b 488B45E8      mov rax, QWORD PTR [rbp-24]
  27 001f 8910          mov DWORD PTR [rax], edx
   7:main2.c       ****     *b=t;
  28                    .loc 1 7 0
  29 0021 488B45E0      mov rax, QWORD PTR [rbp-32]
  30 0025 8B55FC        mov edx, DWORD PTR [rbp-4]
  31 0028 8910          mov DWORD PTR [rax], edx
   8:main2.c       **** }


Добавлено через 7 минут
Вот вам команжа
gcc -O0 -c -g -Wa,-a,-ad -masm=intel main.c > list
Весто 0 поставьте 1,2,3 и изучайте.
1
ValeryS
Модератор
8063 / 5947 / 788
Регистрация: 14.02.2011
Сообщений: 20,500
Завершенные тесты: 1
29.01.2014, 19:49 6
Цитата Сообщение от Pershin Посмотреть сообщение
a^=b^=a^=b;
Цитата Сообщение от Pershin Посмотреть сообщение
плохо, это undefined behaviour,
правильно.
кто гарантирует порядок присвоений?
например строка
C
1
A=B=C=D=5;
гарантируется что после точки с запятой во всех переменных будет 5
но никто не гарантировал что
сначала D=5 потом C=D потом B=C потом A=B
компилятор вполне может поменять порядок, а может вообще записать во все переменные пятерку чёхом
прочитай про точки следования
Цитата Сообщение от Pershin Посмотреть сообщение
и я успешно пользовался второй записью, как более короткой,
В смысле буковки экономил?
Цитата Сообщение от Pershin Посмотреть сообщение
Однако, как сегодня выяснилось, вторая запись перестает работать,
вот и нарвался
Цитата Сообщение от Pershin Посмотреть сообщение
вот вторая выводит числа 0 и 5 вместо 10 и 5.
вполне мог схороть сначала одну переменную между собой, удобней ему так, адрес менять не надо,
а потом с 0 хорить другую
порядок присвоения не определен
0
HighPredator
5958 / 2085 / 736
Регистрация: 10.12.2010
Сообщений: 5,907
Записей в блоге: 3
30.01.2014, 11:43 7
Проблема с обменом, описанная Pershin, очень похожа на баг стандарта № 222 Seqeuence points and l-value returning operators (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#222). Решение, судя по документу, было предложено на основании решения бага № 637 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637). Насколько хорошо исполнено - без понятия. Однако на 2010 студии поведение как Си компилятора так и С++ на данном примере однозначное.
0
Pershin
0 / 0 / 0
Регистрация: 15.07.2013
Сообщений: 14
31.01.2014, 11:29  [ТС] 8
Всем спасибо, а особенно vua72 за указание способа и прямой команды, как самому выяснять подобные вещи. Почитал ассемблерные листинги и всё прояснилось.

Хочу отметить интересный факт - gcc "неправильно" считает swap, только если не указывать флаг оптимизации вообще (или -O0). Уже на -O1, а тем более на -O2, он считает всё правильно.

1) -O0
Используется аж 4 регистра. Подсчёт производится так: *a=5^(*b=10^(*a=5^10)), начиная с самой внутренней скобки. Это даёт *a=0.
2) -O1
Используется 2 регистра, считает как *a=*b^*a; *b=*b^*a; *a=*b^*a; Интересно, что компилятор поменял "классический" порядок аргументов в 1 и 3 выражениях.
3) -O2
Тоже используется 2 регистра, но более рационально, на мой взгляд. Правда, в конце зачем-то идёт четвертый xor одного регистра с самим собой (это он его так обнуляет??)
Вычисление идёт как *a=*a^*b; *b=*b^*a; *a=*b^*a (опять сменен порядок в одном выражении).
0
Charles Kludge
Клюг
7656 / 3171 / 383
Регистрация: 03.05.2011
Сообщений: 8,381
31.01.2014, 13:12 9
Ну да, осталось добавить как это делает Warerloo.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
; void swap(int *a, int *b)
swap:
    push        ebx 
    push        esi 
    mov         eax,dword ptr 0cH[esp] 
    mov         edx,dword ptr 10H[esp] 
 
; {
;     *a^=*b^=*a^=*b;
    mov         ecx,dword ptr [edx] 
    mov         ebx,dword ptr [eax] 
    xor         ebx,ecx 
    mov         dword ptr [eax],ebx 
    mov         esi,dword ptr [edx] 
    xor         esi,ebx 
    mov         dword ptr [edx],esi 
    xor         dword ptr [eax],esi 
 
; };
    pop         esi 
    pop         ebx 
    ret
0
Alex5
1126 / 785 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
01.02.2014, 13:38 10
Цитата Сообщение от Pershin Посмотреть сообщение
C++
1
2
3
4
void swap(int *a, int *b)  /* Error ! */
{
 *a^=*b; *b^=*a; *a^=*b;
}
Первая форма записи работает
Попробуйте, как работает, когда оба параметра одинаковы: swap( &a, &a )

Добавлено через 23 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
A=B=C=D=5;
но никто не гарантировал что
сначала D=5 потом C=D потом B=C потом A=B
"Существует несколько операторов присваивания. Они выполняются справа налево."
(Керниган, Ритчи.Язык программирования Си. Приложение A7.17.Выражения присваивания.)

Добавлено через 7 минут
Цитата Сообщение от Pershin Посмотреть сообщение
Википедия говорит, что вторая форма записи - плохо, это undefined behaviour
В приведённой ссылке на Википедию и сказано, почему.
x = x ^ (y ^= (x ^= y));
Вычисления левого (x) и правого (y ^= (x ^= y)) операндов операции ^ не упорядочены по отношению друг к другу
0
ValeryS
Модератор
8063 / 5947 / 788
Регистрация: 14.02.2011
Сообщений: 20,500
Завершенные тесты: 1
01.02.2014, 17:23 11
Цитата Сообщение от Alex5 Посмотреть сообщение
"Существует несколько операторов присваивания. Они выполняются справа налево."
ну а как они выполняются?
в стандарте не нашел, может плохо искал
решил дизасемблировать вот такой код
C
1
2
3
4
char a,b,c,d;
 static char e;
 a=b=c=d=5; 
 e=a+b+c+d;
CodeVisionAVR
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                ;   a -> R17
                 ;  b -> R16
                 ;  c -> R19
                 ;  d -> R18
000085 e0e5         LDI  R30,LOW(5)
000086 2f2e         MOV  R18,R30
000087 2f3e         MOV  R19,R30
000088 2f0e         MOV  R16,R30
000089 2f1e         MOV  R17,R30
                 ; 0000 0029  e=a+b+c+d;
00008a 2fe0         MOV  R30,R16
00008b 0fe1         ADD  R30,R17
00008c 0fe3         ADD  R30,R19
00008d 0fe2         ADD  R30,R18
00008e 93e0 016c    STS  _e_S0000000000,R30
что равносильно
C
1
2
3
4
d=5;
c=5;
b=5;
a=5;
VS2008

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
01161084 C6 45 FD 05      mov         byte ptr [d],5 
01161088 8A 45 FD         mov         al,byte ptr [d] 
0116108B 88 45 FC         mov         byte ptr [c],al 
0116108E 8A 4D FC         mov         cl,byte ptr [c] 
01161091 88 4D FE         mov         byte ptr [b],cl 
01161094 8A 55 FE         mov         dl,byte ptr [b] 
01161097 88 55 FF         mov         byte ptr [a],dl 
 e=a+b+c+d;
0116109A 0F BE 45 FF      movsx       eax,byte ptr [a] 
0116109E 0F BE 4D FE      movsx       ecx,byte ptr [b] 
011610A2 03 C1            add         eax,ecx 
011610A4 0F BE 55 FC      movsx       edx,byte ptr [c] 
011610A8 03 C2            add         eax,edx 
011610AA 0F BE 4D FD      movsx       ecx,byte ptr [d] 
011610AE 03 C1            add         eax,ecx 
011610B0 A2 70 33 16 01   mov         byte ptr [e (1163370h)],al
C
1
2
3
4
d=5;
c=d;
b=c;
a=b;
абсолютно разные коды(хотя во всех переменных 5), и я не уверен что третий компилятор не сделает еще как нибудь по другому
0
Evg
Эксперт CАвтор FAQ
21088 / 8105 / 628
Регистрация: 30.03.2009
Сообщений: 22,437
Записей в блоге: 30
01.02.2014, 17:49 12
Цитата Сообщение от Pershin Посмотреть сообщение
1) -O0
Используется аж 4 регистра. Подсчёт производится так: *a=5^(*b=10^(*a=5^10)), начиная с самой внутренней скобки. Это даёт *a=0.
2) -O1
Используется 2 регистра, считает как *a=*b^*a; *b=*b^*a; *a=*b^*a; Интересно, что компилятор поменял "классический" порядок аргументов в 1 и 3 выражениях.
3) -O2
Тоже используется 2 регистра, но более рационально, на мой взгляд. Правда, в конце зачем-то идёт четвертый xor одного регистра с самим собой (это он его так обнуляет??)
Вычисление идёт как *a=*a^*b; *b=*b^*a; *a=*b^*a (опять сменен порядок в одном выражении).
Это только подтверждает то, что сказано в посте #6. И именно этот пост является ответом на вопрос, а вовсе не тот, который ты отметил (потому что там ответа на вопрос вообще нет). К ответу я бы так же добавил пост #7. В качестве оффтопа заметил бы, что обмен двух переменных через третью работает быстрее, чем с xor'ами (не говоря уж о том, что через xor'ы по языку не поменяешь переменные произвольного типа, а только целочисленные)
0
Somebody
2818 / 1628 / 252
Регистрация: 03.12.2007
Сообщений: 4,223
Завершенные тесты: 3
01.02.2014, 17:58 13
C99 6.5.16:
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand. The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point.
C11 по смыслу то же, но ещё примечание:
The implementation is permitted to read the object to determine the value but is not required to, even
when the object has volatile-qualified type.
0
Alex5
1126 / 785 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
01.02.2014, 23:08 14
Цитата Сообщение от ValeryS Посмотреть сообщение
кто гарантирует порядок присвоений?
ValeryS, A=B=C эквивалентно A=(B=C) . Невозможно присвоить значение переменной A, пока не вычислен результат B=C. Если C не является константой, то компилятор обязан сгенерировать код, в котором сначала B=C, потом результат присваивается A
0
ValeryS
Модератор
8063 / 5947 / 788
Регистрация: 14.02.2011
Сообщений: 20,500
Завершенные тесты: 1
01.02.2014, 23:18 15
Цитата Сообщение от Alex5 Посмотреть сообщение
ValeryS, A=B=C эквивалентно A=(B=C)
ссылку пожалуйста
Цитата Сообщение от Alex5 Посмотреть сообщение
в котором сначала B=C, потом результат присваивается A
вот если бы было
C++
1
a=b==c;
то я бы согласился, нет внутри точки следования сначала и потом
что будет
C++
1
a=++b=++c=5;
Добавлено через 1 минуту
вот хороший рассказ про точки следования
http://alenacpp.blogspot.ru/2005/11/sequence-points.html
0
Alex5
1126 / 785 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
01.02.2014, 23:34 16
Порядок выполнения присваиваний
5.17 Assignment and compound assignment operators
1 The assignment operator (=) and the compound assignment operators all group right-to-left
(Working Draft, Standard for Programming Language C++, Date: 2012-01-16)
1
Somebody
2818 / 1628 / 252
Регистрация: 03.12.2007
Сообщений: 4,223
Завершенные тесты: 3
02.02.2014, 00:01 17
Тема вообще по C, а тут уже про Плюсы пошло...
В C++11 нет точек следования, там отношение sequenced before, и там при
C++
1
a = ++b = ++c = 5;
всё должно быть нормально.
В C++03 - однозначно ub.
Alex5, grouped, не executed, left-to-right - это только ассоциативность, а не порядок выполнения.
0
Alex5
1126 / 785 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
02.02.2014, 11:14 18
Порядок вычисления выражения - какие могут быть неоднозначности?
1) Не задан порядок вычисления операндов. A^B - Сначала вычисляется A, потом B ? Или наоборот? Не определено.
2) Что раньше: вычисление операндов или выполнение самой операции?
A+B, сложение всегда после A и после B. A&&B Если результат A ноль, то B вообще не вычисляется.
3) Порядок вычисления операторов с разным приоритетом. Определён однозначно. A + B * C , сначала умножение, потом сложение
4) Порядок вычисления операторов с одинаковым приоритетом. Определён однозначно. A + B + C, сначала левый +, потом правый + . Ассоциативность сложения "слева направо".
Пример 1.
C++
1
 *p = *( ++ p ); /* Ошибка! Нет гарантии, что ++p будет выполнено раньше, *p */
Пример 2.
C++
1
 x = a ^ ( expression ); /* Не определено, что раньше вычисляется. a  или  (  expression  )  */
0
ValeryS
Модератор
8063 / 5947 / 788
Регистрация: 14.02.2011
Сообщений: 20,500
Завершенные тесты: 1
05.02.2014, 08:54 19
Alex5,
спасибо что ткнул в пункт, я как то его пропустил
но там говорится о том что
при
C++
1
a=b=c=5;
что сначала присвоиться c потом b потом a
но что присвоится? вот вопрос?
Цитата Сообщение от Alex5 Посмотреть сообщение
потом результат присваивается
результат равен 5( в данном случае)
посему один компилятор присвоил всем переменным 5
а другой сначала присвоил переменной а потом эти значения скопировал
значит, я делаю вывод, может не правильный, все отдается на откуп компилятору
представим такой гипотетический случай
в c записалась 5
в это время, другой поток перехватывает управление и увеличивает её на 1
что должно быть в b и a? 5 или 6????
0
CheshireCat
Эксперт С++
2916 / 1265 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
05.02.2014, 10:23 20
Цитата Сообщение от Alex5 Посмотреть сообщение
4) Порядок вычисления операторов с одинаковым приоритетом. Определён однозначно. A + B + C, сначала левый +, потом правый + . Ассоциативность сложения "слева направо".
Вот тут хотелось бы увидеть ссылочку на пункт Стандарта....
0
05.02.2014, 10:23
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.02.2014, 10:23

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Обмен значениями двух переменных
Помогите решить задачу Составить программу обмена значениями двух переменных величин.

Обмен значений двух переменных
Ниже решение задачи (Задана целочисленная последовательность A = (a i), i = 1..n, n <= 100.*...

Обмен значениями трех переменных
Помогите составить программу пожалуйста Составить программу обмена значениями трех переменных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.