Порядок действий для указателей - PullRequest
0 голосов
/ 27 апреля 2011

Не могли бы вы объяснить порядок операций для следующей функции, которая переворачивает строку?

//http://www.perlmonks.org/?node_id=589993 source of method
/* reverse a string in place, return str */
static char* reverse(char* str)
{
    char* left  = str;
    char* right = left + strlen(str) - 1;
    char  tmp;
    while (left < right)
    {
        tmp      = *left;
        *left++  = *right;//This part is real confusing...Does ++ happen after the assignment?
        *right-- = tmp;//This one is just as bad
    }
    return str;
}

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

Ответы [ 7 ]

4 голосов
/ 27 апреля 2011
*left++  = *right

В этом операторе *left присваивается *right, а затем после этого все left (не *left) увеличивается.Та же логика применима и к *right--

Таким образом, переписанный псевдокод будет следующим:

while(not halfway)
{
    tmp = left value
    left value = right value
    left position += 1
    right value = tmp
    right position -= 1        
}
0 голосов
/ 27 апреля 2011
Происходит ли ++ после назначения?

Нет.Приращение p, вероятно, происходит до того, как происходит присвоение, но это не очень важно здесь.

Важная часть заключается в том, что присвоение видит только то значение, которое p имело до увеличения p.p++ возвращает не больше p, чем !x возвращает x.

p++ возвращает исходное значение p по тем же строкам, что и

TYPE* post_inc(TYPE* p) {
   TYPE* tmp = p;
   ++p;
   return tmp;
}

Всевместе это выглядит примерно так:

    tmp = *left;

    anon0 = left;
    ++left;
    *anon0 = *right;

    anon1 = right;
    --right;
    *anon1 = tmp;

(Фактический порядок может отличаться.)

0 голосов
/ 27 апреля 2011

Постфиксные операторы (которые включают ++ и --) имеют более высокий приоритет, чем унарные операторы (такие как *). Таким образом, выражение *p++ анализируется как *(p++), поэтому * применяется к результату из p++.

Итак,

*left++ = *right;

эквивалентно

*left = *right;
left++;
0 голосов
/ 27 апреля 2011

Эта строка:

*left++ = *right;

имеет два побочных эффекта: left увеличивается, чтобы указывать на следующий элемент массива, на который он указывает, и значение, считанное с адреса right, сохраняетсяв месте left, указанном до увеличения .Однако не определено упорядочение между тем, происходит ли сохранение переменной-указателя left до или после сохранения до символа, на который она указала.

0 голосов
/ 27 апреля 2011

Вы получили это.

*left++  = *right;
  1. разыменование *right
  2. store (1) в *left
  3. приращение left

*right-- = tmp;
  1. store tmp at *right
  2. уменьшение right

Постфиксный приращение / уменьшение (++ / --) операторы имеют более высокий приоритет, чем разыменование (*).Так что *left++ анализируется как *(left++).Будучи операцией после увеличения, увеличение происходит после этой последовательности (т. Е. После назначения).

0 голосов
/ 27 апреля 2011

Чтобы понять код, проще добавить к нему круглые скобки:

*left++  = *right;

То же, что и:

*(left++) = *right;

Другими словами, ++ применяется куказатель, а не то, на что указывает указатель.

Поскольку это оператор постинкремента, побочный эффект возникает после использования значения left.Другими словами, это то же самое, что:

*left = *right;
left++;
0 голосов
/ 27 апреля 2011

Операторы после декремента выполняются после разыменования и так эффективно (в вашем коде) после назначения.

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