Указатели и петли - PullRequest
       2

Указатели и петли

4 голосов
/ 19 февраля 2011

Это уже давно беспокоит меня: есть ли разница (например, в отношении памяти) между этим

Pointer *somePointer;
for (...)
{
    somePointer = something;
    // do stuff with somePointer
}

и этим

for (...)
{
    Pointer *somePointer = something;
    // do stuff with somePointer
}

Ответы [ 4 ]

4 голосов
/ 19 февраля 2011

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

Pointer *somePointer;
Pointer *somePointer2;
for(loopA)
{
    if(meetsSomeCriteria(somePointer)) break;
}

for(loopB)
{
    if(meetsSomeCriteria(somePointer2)) break; 
}
/* do something with the two pointers */
someFunc(somePointer,somePointer2);
3 голосов
/ 19 февраля 2011

Ну, во-первых, во втором примере somePointer будет действителен только внутри цикла (это область действия), поэтому, если вы хотите использовать его снаружи, вы должны сделать как в фрагменте № 1.
Если мы включим сборкумы видим, что для выполнения второго фрагмента нужно выполнить еще 2 инструкции:

Фрагмент 1:

for(c = 0; c <= 10; c++)
    (*p1)++;  

0x080483c1 <+13>:   lea    -0x8(%ebp),%eax          # eax = &g
0x080483c4 <+16>:   mov    %eax,-0xc(%ebp)          # p1 = g
0x080483c7 <+19>:   movl   $0x0,-0x4(%ebp)          # c = 0
0x080483ce <+26>:   jmp    0x80483e1 <main+45>      # dive in the loop
0x080483d0 <+28>:   mov    -0xc(%ebp),%eax          # eax = p1
0x080483d3 <+31>:   mov    (%eax),%eax              # eax = *p1
0x080483d5 <+33>:   lea    0x1(%eax),%edx           # edx = eax + 1
0x080483d8 <+36>:   mov    -0xc(%ebp),%eax          # eax = p1
0x080483db <+39>:   mov    %edx,(%eax)              # *p1 = edx
0x080483dd <+41>:   addl   $0x1,-0x4(%ebp)          # c++
0x080483e1 <+45>:   cmpl   $0xa,-0x4(%ebp)           # re-loop if needed
0x080483e5 <+49>:   jle    0x80483d0 <main+28>

Фрагмент 2:

for(c = 0; c <= 10; c++) {
    int *p2 = &g;
    (*p2)--;
}
0x080483f0 <+60>:   lea    -0x8(%ebp),%eax          # eax = &g
0x080483f3 <+63>:   mov    %eax,-0x10(%ebp)         # p2 = eax
0x080483f6 <+66>:   mov    -0x10(%ebp),%eax         # eax = p2
0x080483f9 <+69>:   mov    (%eax),%eax              # eax = *p2
0x080483fb <+71>:   lea    -0x1(%eax),%edx          # edx = eax - 1
0x080483fe <+74>:   mov    -0x10(%ebp),%eax         # eax = p2
0x08048401 <+77>:   mov    %edx,(%eax)              # *p2 = edx
0x08048403 <+79>:   addl   $0x1,-0x4(%ebp)          # increment c
0x08048407 <+83>:   cmpl   $0xa,-0x4(%ebp)          # loop if needed
0x0804840b <+87>:   jle    0x80483f0 <main+60>

Хорошо, разницав первых двух инструкциях фрагмента # 2, которые выполняются в каждом цикле, в то время как в первом фрагменте они выполняются непосредственно перед входом в цикл.
Надеюсь, я был понятен.;)

0 голосов
/ 19 февраля 2011

посмотрите аналогичный ответ для stackoverflow здесь с некоторыми хорошими ответами.Однако это, вероятно, не зависит от компилятора / языка ...

0 голосов
/ 19 февраля 2011

Ну, с первой версией вы должны выпустить только один раз, после цикла.Во второй версии вы не можете использовать указатель извне цикла, поэтому вам нужно освободить внутри цикла.С точки зрения памяти, это не должно иметь большого значения, но я думаю, у вас есть дополнительные затраты во втором примере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...