Подтвердить что ты не робот

Операции указателя и приоритет оператора в C

Фон

Просто пообщался с парнем C сегодня, и мы не согласились на следующее:

int intgA[2] = { 1, 2 };
int intgB[2] = { 3, 5 };

int *intAPtr = intgA;
int *intBPtr = intgB;

Итак, когда мы делаем:

*intAPtr++ = *intBPtr++;

Мой анализ

Во-первых:

intBPtr увеличивается на единицу, указывая теперь на адрес 5. Тогда, уважение, держащее значение 5;

intAPtr также увеличивается на единицу, теперь указывая на адрес 2. Впоследствии ссылка и значение равно 2;

Наконец:

2 заменяется на 5.

Итак, соответственно: 5 и 5.

Его анализ

Значение *intBPtr сначала присваивается *intAPtr.

Следовательно, они становятся: 3 и 3.

Затем оба *intAPtr и *intBPtr увеличиваются на единицу.

Таким образом, соответственно они становятся: 4 и 4.

Мое предположение

Я думал, что оператор ++ имеет приоритет как над *, так и =, поэтому мое утверждение.

Например, если бы мы имели:

*intAPtr++; 

Результат должен быть 2, верно? Поскольку мы сначала увеличиваем указатель, а затем разыгрываем.

Итак, почему в приведенном выше случае, как он утверждает, мы сначала присваиваем значение intBPtr значению intAPtr и увеличиваем значения last?

После того, как вы сделали все предложения, я запустил код в IDE, и результат подтвердил результат @sujin:

Хотя это подтверждает, что я был прав, по крайней мере, с точки зрения приоритета:

То: *intAPtr++ = *intBPtr++;

intAPtr++ имеет более высокий приоритет, что приводит к: intAPtr увеличивает свой адрес на 1.

Теперь указывая на: адрес 2.

И аналогично:

intBPtr++ также увеличивается на 1 (адрес).

Теперь указывая на: адрес 5.

Затем он * поворачивается:

Таким образом, оба получают разыменованные (*) соответственно 2 и 5.

Но проблема существует еще потому, что присваивание выше (=), похоже, не произошло.

Если бы это было так, то получилось бы 5.

Ждем дальнейшего просвещения.

4b9b3361

Ответ 1

Утверждение

*intAPtr++ = *intBPtr++;

анализируется как

*(intAPtr++) = *(intBPtr++);

и разбивается следующим образом:

  • Значение, указанное в настоящее время на intBPtr (3), присваивается местоположению, на которое указывает intAPtr (intgA[0]);
  • Указатели intAPtr и intBPtr увеличиваются.

Точный порядок, в котором происходят эти вещи, не указан; вы не можете полагаться на intBPtr, увеличивающийся после intAPtr или наоборот, и вы не можете полагаться на назначение, которое происходит до приращений и т.д.

Итак, к тому времени, когда все это будет сделано, intgA[0] == 3 и intAPtr == &intgA[1] и intBPtr == &intgB[1].

Выражение a++ оценивается значением a до приращения.

Ответ 2

Ты и другой парень оба ошибаетесь!

Либо,
1. оба указателя увеличиваются сначала, а затем выполняется присвоение или
2. один указатель увеличивается, затем выполняется назначение, затем увеличивается другой указатель или 3. Первое присваивание происходит, а затем указатели увеличиваются.

Но правило состоит в том, что все побочные эффекты одного оператора должны быть полными до начала следующего утверждения. Имейте в виду, что должны использоваться исходные значения. Пока используется исходное значение, приращение может произойти в любое время.

C-faq: 3.2:

не гарантируется, что приращение или декремент выполняются сразу же после отказа от предыдущего значения и перед оценкой любой другой части выражения. Просто гарантируется, что обновление будет выполняться когда-нибудь, прежде чем выражение будет считаться "завершенным" .

Подробнее читайте , предоставленный Эрик Липперт.

Ответ 3

Да, ++ привязывается более жестко, чем *, но вы неправильно поняли, как это работает. var++ увеличивает var, но до приращения вычисляет значение var. Вы можете придумать это как синтаксический сахар для (var += 1, var - 1), если хотите.

Еще один способ подумать об этом: если бы он работал так, как вы думали, то не было бы никакой разницы между var++ и ++var, и один из них не был бы включен в язык в первое место. C почти не имеет избыточности.

(Приоритет привязки имеет значение, например, означает, что *var++ увеличивает значение переменной var, тогда как (*var)++ увеличивает значение в ячейке памяти в *var.)

Ответ 4

Основной эффект оператора ++ заключается в создании значения его операнда (без его увеличения). Побочным эффектом является увеличение операнда.

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

В *x++, который анализируется как *(x++), оператор * применяется к значению, создаваемому основным эффектом, поэтому операция * такая же, как если бы оценивалась *x. Приращение происходит "сбоку", вне оценки основного выражения, поэтому он не принимает участия в определении значения *x++.

Ответ 5

Пример кода (в linux):

#include <stdio.h>
#include <stdlib.h>
int main() {
    int intgA[2] = { 1, 2 };
    int intgB[2] = { 3, 5 };
    int *intAPtr = intgA; //1
    int *intBPtr = intgB; //3
    *intAPtr++ = *intBPtr++;
    // *intAPtr = *intBPtr;
    // *intAPtr++ = 25; 
    printf("op: %d %d\n", *intAPtr, *intBPtr);

   return 0;
}

выход:

op: 2 5

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

Ответ 6

Я согласен с ответом Джона Боде, чтобы немного упростить его Я просто напишу его в коде:

   *intAptr = * intBPtr;

равно:

   *intAptr =*intBPtr 
   intAPtr+=1;
   inrBPtr+=1;

так что мы получаем: intAPtr указывает на 2 intBPtr указывает на 5