С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
frusty
11 / 11 / 3
Регистрация: 24.12.2015
Сообщений: 91
Завершенные тесты: 2
1

Есть ли различие между ++i и i++ для цикла

06.09.2016, 11:36. Просмотров 929. Ответов 3
Метки нет (Все метки)

C#
1
for(int i = 0; i < 5; i++)
Есть хоть одна ситуация, где замена i++ на ++i будет иметь смысл?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.09.2016, 11:36
Ответы с готовыми решениями:

Что возвращает void, или различие между процедурами и функциями
Здраствуйте, пару месяцев назад, когда я бегал по собеседованиям, меня...

В чем различие между методом типа void и методом с возвращаемым значением?
Я начал читать Троелсона еще до изучение шарпа в институте и заметил, что автор...

Как из цикла вывести данные для другого цикла?
Вообщем такая фигня... Как из цикла вывести данные для другого цикла? а то...

Есть ли различие между холодильником и контейнером холодильным?
Я тут на днях зашел в магазин и увидел холодильники и контейнеры холодильные, а...

есть ли различие между сервеной озу и перс. комп-ра?
http://www.nix.ru/autocatalog/memory_modules_kingston/Kingston_HyperX_KHX1600C9D...

3
Lutk
71 / 66 / 29
Регистрация: 28.10.2013
Сообщений: 248
Завершенные тесты: 2
06.09.2016, 11:54 2
Постинкремент:
C#
1
2
3
4
5
6
7
var x = 0;
while (x != 3) {
    Console.WriteLine(x++);
}
// 0
// 1
// 2
Преинкремент:
C#
1
2
3
4
5
6
7
var x = 0;
while (x != 3) {
    Console.WriteLine(++x);
}
// 1
// 2
// 3
0
novikov.ea
1018 / 788 / 285
Регистрация: 10.06.2011
Сообщений: 1,490
06.09.2016, 13:08 3
Лучший ответ Сообщение было отмечено frusty как решение

Решение

Lutk, вопрос был именно про использование в цикле.
На stackoverflow можно много чего почитать на эту тему, но общий смысл раскрывает этот пост
Если декомпилировать код с пред- и постинкреметами переменной i в циклах, то CIL будет одинаковым
C#
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace PreOrPostIncrement
{
    class Program
    {
        static int SomethingToIncrement;
 
        static void Main(string[] args)
        {
            PreIncrement(1000);
            PostIncrement(1000);
            Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
        }
 
        static void PreIncrement(int count)
        {
            /*
            .method private hidebysig static void  PreIncrement(int32 count) cil managed
            {
              // Code size       25 (0x19)
              .maxstack  2
              .locals init ([0] int32 i)
              IL_0000:  ldc.i4.0
              IL_0001:  stloc.0
              IL_0002:  br.s       IL_0014
              IL_0004:  ldsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
              IL_0009:  ldc.i4.1
              IL_000a:  add
              IL_000b:  stsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
              IL_0010:  ldloc.0
              IL_0011:  ldc.i4.1
              IL_0012:  add
              IL_0013:  stloc.0
              IL_0014:  ldloc.0
              IL_0015:  ldarg.0
              IL_0016:  blt.s      IL_0004
              IL_0018:  ret
            } // end of method Program::PreIncrement             
             */
            for (int i = 0; i < count; ++i)
            {
                ++SomethingToIncrement;
            }
        }
 
        static void PostIncrement(int count)
        {
            /*
                .method private hidebysig static void  PostIncrement(int32 count) cil managed
                {
                  // Code size       25 (0x19)
                  .maxstack  2
                  .locals init ([0] int32 i)
                  IL_0000:  ldc.i4.0
                  IL_0001:  stloc.0
                  IL_0002:  br.s       IL_0014
                  IL_0004:  ldsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
                  IL_0009:  ldc.i4.1
                  IL_000a:  add
                  IL_000b:  stsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
                  IL_0010:  ldloc.0
                  IL_0011:  ldc.i4.1
                  IL_0012:  add
                  IL_0013:  stloc.0
                  IL_0014:  ldloc.0
                  IL_0015:  ldarg.0
                  IL_0016:  blt.s      IL_0004
                  IL_0018:  ret
                } // end of method Program::PostIncrement
             */
            for (int i = 0; i < count; i++)
            {
                SomethingToIncrement++;
            }
        }
    }
}
0
Tsin
724 / 468 / 184
Регистрация: 30.12.2012
Сообщений: 1,270
Записей в блоге: 2
Завершенные тесты: 3
06.09.2016, 14:08 4
Цитата Сообщение от frusty Посмотреть сообщение
Есть хоть одна ситуация, где замена i++ на ++i будет иметь смысл?
На практике такое вряд ли встретится, но ситуация имеет место быть.

Посмотрите на этот код:
C#
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
public class Program
{
    public static int number = 0;
 
    static void Main(string[] args)
    {
        PreInc();
        PostInc();
    }
 
    static void PreInc()
    {
        Check(++number);
    }
 
    static void PostInc()
    {
        Check(number++);
    }
 
    static void Check(int value)
    {
        Console.WriteLine("Passed: {0}, Current: {1}", value, Program.number);
    }
}
На выходе хотелось бы увидеть что-то типа:
Код
Passed: 1, Current: 1
Passed: 2, Current: 2
Но получится:
Код
Passed: 1, Current: 1
Passed: 1, Current: 2
Простыми словами:

В префиксной нотации
  1. Увеличиваем значение переменной number
  2. Отдаём новое значение в функцию

В постфиксной
  1. Значение переменной (number) сохраняем (во временной переменной t)
  2. В переменную (number) записываем значение временной переменной, увеличенное на 1 (t+1)
  3. Отдаём старое значение (t) в функцию.

Поэтому мы имеем в столбце Passed две единицы
1) number с 0 изменился на 1 и был передан в функцию
2) number с 1 изменился на 2 но в функцию попало старое значение (1)

А в столбце Current единицу и двойку
1) number с 0 изменился на 1
2) number с 1 изменился на 2

Почему так происходит (осторожно, IL)
Рассмотрим IL, который будет сгенерирован:
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
.method private hidebysig static void  PreInc() cil managed
{
  // Размер кода:       19 (0x13)
  .maxstack  8
  IL_0000:  ldsfld     int32 Test.Program::number
  IL_0005:  ldc.i4.1
  IL_0006:  add
  IL_0007:  dup
  IL_0008:  stsfld     int32 Test.Program::number
  IL_000d:  call       void Test.Program::Check(int32)
  IL_0012:  ret
} // end of method Program::PreInc
 
.....
 
.method private hidebysig static void  PostInc() cil managed
{
  // Размер кода:       19 (0x13)
  .maxstack  8
  IL_0000:  ldsfld     int32 Test.Program::number
  IL_0005:  dup
  IL_0006:  ldc.i4.1
  IL_0007:  add
  IL_0008:  stsfld     int32 Test.Program::number
  IL_000d:  call       void Test.Program::Check(int32)
  IL_0012:  ret
} // end of method Program::PostInc
Оставлю только интересующий нас момент и прокомментирую различия:
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
.method private hidebysig static void  PreInc() cil managed
{
  IL_0000:  ldsfld     int32 Test.Program::number      //Кладём на стек значение переменной number (0)
  IL_0005:  ldc.i4.1                                   //Кладём на стек единицу (0 1)
  IL_0006:  add                                        //Берём два значения со стека, складываем, кладём обратно (1)
  IL_0007:  dup                                        //Дублируем значение со стека (1 1)
  IL_0008:  stsfld     int32 Test.Program::number      //Забираем значение со стека в number (number = 1)
  IL_000d:  call       void Test.Program::Check(int32) //Забираем со стека значение и вызываем функцию: Check(1)
} // end of method Program::PreInc
 
//Получаем выход: Passed: 1, Current: 1
...
 
.method private hidebysig static void  PostInc() cil managed
{
  IL_0000:  ldsfld     int32 Test.Program::number      //Кладём на стек значение переменной number (1)
  IL_0005:  dup                                        //Дублируем значение со стека (1 1)
  IL_0006:  ldc.i4.1                                   //Кладём на стек единицу (1 1 1)
  IL_0007:  add                                        //Берём два значения со стека, складываем, кладём обратно (1 2)
  IL_0008:  stsfld     int32 Test.Program::number      //Забираем значение со стека в number (number = 2)
  IL_000d:  call       void Test.Program::Check(int32) //Забираем со стека значение и вызываем функцию: Check(1)
} // end of method Program::PostInc
 
//Получаем выход: Passed: 1, Current: 2
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.09.2016, 14:08

Различие между G4600 i5-7400 i7-7700 для общего быстродействия системы
Собираю конфиг для домашнего использования(OC win10). В игры играть не...

Опишите сходство и различие использования операторов цикла for, while
0пишите сходство и различие использования операторов цикла for, while и do ......

Есть ли различие?
У меня вопрос есть ли какие либо различия в шифровании и ЦП в Lotus версий...


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

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

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