Постинкремент на разыменованном указателе?

Я обнаружил проблему, проблема заключалась в том, что приложением по умолчанию для PDF было Microsoft Edge, я изменил его на Acrobat Reader, и теперь оно печатает.

51
задан Dukeling 25 May 2017 в 01:57
поделиться

8 ответов

Из-за правил приоритета операторов и того факта, что ++ - постфиксный оператор, add_one_v2 () разыменовывает указатель, но ++ фактически применяется к самому указателю . Однако помните, что C всегда использует передачу по значению: add_one_v2 () увеличивает свою локальную копию указателя, что никак не повлияет на значение, хранящееся по этому адресу. .

В качестве теста замените add_one_v2 () этими битами кода и посмотрите, как это повлияет на вывод:

void add_one_v2(int *our_var_ptr)
{
    (*our_var_ptr)++;  // Now stores 64
}

void add_one_v2(int *our_var_ptr)
{
    *(our_var_ptr++);  // Increments the pointer, but this is a local
                       // copy of the pointer, so it doesn't do anything.
}
40
ответ дан 7 November 2019 в 09:46
поделиться

Изображения стоят приблизительно тысячу слов (плюс-минус приблизительно миллион)..., и символы могут быть изображениями (и наоборот.)

те Soвёєfor из нас, кто ищет tl;dr (оптимизированное потребление данных) и все же, хотят “ (главным образом) lossless” кодирование, векторные изображения/изображения/иллюстрации/демонстрации являются главными.

, Другими словами, просто проигнорируйте мои последние 2 оператора и посмотрите ниже.

Valid forms:


*a++ ≣ *(a++)
≣ (a++)[0] ≣ a++[0]
≣ 0[a++] // Don't you dare use this (“educational purposes only”)
// These produce equivalent (side) effects;
≡ val=*a,++a,val
≡ ptr=a,++a,*ptr
≡ *(ptr=a,++a,ptr)

*++a ≣ *(++a)
≣ *(a+=1) ≣ *(a=a+1)
≣ (++a)[0] ≣ (a+=1)[0] ≣ (a=a+1)[0] // ()'s are necessary
≣ 0[++a] // 0[a+=1], etc... “educational purposes only”
// These produce equivalent (side) effects:
≡ ++a,*a
≡ a+=1,*a
≡ a=a+1,*a

++*a ≣ ++(*a)
≣ *a+=1
≣ *a=*a+1
≣ ++a[0] ≣ ++(a[0])
≣ ++0[a] // STAY AWAY

(*a)++ // Note that this does NOT return a pointer;
// Location `a` points to does not change
// (i.e. the 'value' of `a` is unchanged)
≡ val=*a,++*a,val

Notes

/* Indirection/deference operator must pr̲e̲cede the target identifier: */
a++*;
a*++;
++a*;
0
ответ дан 7 November 2019 в 09:46
поделиться

Это одна из тех маленьких ошибок, которые делают C и C ++ так весело. Если вы хотите изменить свой мозг, выясните это:

while (*dst++ = *src++) ;

Это строковая копия. Указатели продолжают увеличиваться до тех пор, пока не будет скопирован символ с нулевым значением. Как только вы узнаете, почему этот трюк работает, вы больше никогда не забудете, как ++ работает с указателями.

PS Вы всегда можете переопределить порядок операторов с помощью круглых скобок. Следующее будет увеличивать указанное значение, а не сам указатель:

(*our_var_ptr)++;
62
ответ дан 7 November 2019 в 09:46
поделиться

Оператор '++' имеет более высокий приоритет над оператором '*', что означает, что адрес указателя будет увеличиваться перед разыменованием.

Оператор «+», однако, имеет более низкий приоритет, чем «*».

0
ответ дан 7 November 2019 в 09:46
поделиться

ОК,

*our_var_ptr++;

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

  1. Сначала происходит разыменование, и вы получаете ячейку памяти, обозначенную our_var_ptr (которая содержит 63).
  2. Затем выражение оценивается, результат 63 равен по-прежнему 63.
  3. Результат отбрасывается (вы ничего с ним не делаете).
  4. our_var_ptr затем увеличивается ПОСЛЕ оценки. Он меняет то место, куда указывает указатель, а не то, на что он указывает.

Фактически это то же самое, что и следующее:

*our_var_ptr;
our_var_ptr = our_var_ptr + 1; 

Имеет смысл? Ответ Марка Рэнсома является хорошим примером этого, за исключением того, что он фактически использует результат.

  • Результат отбрасывается (вы ничего с ним не делаете).
  • our_var_ptr затем увеличивается ПОСЛЕ оценки. Он меняет то место, куда указывает указатель, а не то, на что он указывает.
  • Фактически это то же самое, что и следующее:

    *our_var_ptr;
    our_var_ptr = our_var_ptr + 1; 
    

    Имеет смысл? Ответ Марка Рэнсома является хорошим примером этого, за исключением того, что он фактически использует результат.

  • Результат отбрасывается (вы ничего с ним не делаете).
  • our_var_ptr затем увеличивается ПОСЛЕ оценки. Он меняет то место, куда указывает указатель, а не то, на что он указывает.
  • Фактически это то же самое, что и следующее:

    *our_var_ptr;
    our_var_ptr = our_var_ptr + 1; 
    

    Имеет смысл? Ответ Марка Рэнсома является хорошим примером этого, за исключением того, что он фактически использует результат.

    35
    ответ дан 7 November 2019 в 09:46
    поделиться

    Как указывали другие, приоритет оператора приводит к тому, что выражение в функции v2 будет выглядеть как * (our_var_ptr ++) .

    Однако, поскольку это - постинкрементного оператора, было бы не совсем верно сказать, что он увеличивает указатель, а затем разыменовывает его. Если бы это было правдой, я не думаю, что вы получили бы 63 на выходе, поскольку он вернул бы значение в следующей ячейке памяти. На самом деле, я считаю, что логическая последовательность операций следующая:

    1. Сохранить текущее значение указателя
    2. Увеличить указатель
    3. Разыменовать значение указателя, сохраненное на шаге 1

    Как объяснялось htw, вы не видит изменение значения указателя, потому что он передается по значению функции.

    6
    ответ дан 7 November 2019 в 09:46
    поделиться
    import getpass
    print getpass.getuser()
    

    См. Документацию модуля getpass .

    getpass.getuser ( )

    Возвращает «логин» пользователя. Доступность: Unix, Windows.

    Эта функция проверяет переменные среды LOGNAME, USER, LNAME и USERNAME, по порядку, и возвращает значение первого который установлен в непустую строку. Если не заданы, имя входа из база паролей возвращается на системы, поддерживающие модуль pwd, но указатель равен

  • приращение указателя в add_one_v2 происходит после разыменования
  • Почему?

    • Потому что ++ связывает более жестко чем * (как разыменование или умножение), поэтому приращение в add_one_v2 применяется к указателю, а не к тому, на что он указывает.
    • post приращения происходят после оценка термина, поэтому разыменование получает первое значение в массиве (элемент 0).
    7
    ответ дан 7 November 2019 в 09:46
    поделиться

    our_var_ptr - указатель на некоторую память. т.е. это ячейка памяти, в которой хранятся данные. (в данном случае 4 байта в двоичном формате int).

    * our_var_ptr - это разыменованный указатель - он переходит в то место, на которое «указывает» указатель.

    ++ увеличивает значение на единицу.

    поэтому , * our_var_ptr = * our_var_ptr + 1 разыменовывает указатель и добавляет единицу к значению в этом месте.

    Теперь добавьте приоритет оператора - прочтите его как (* our_var_ptr) = (* our_var_ptr) +1 и вы видите, что разыменование происходит первым, поэтому вы берете значение и увеличиваете его.

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

    Мой совет, при использовании разыменования (или чего-либо еще) используйте скобки чтобы ваше решение было ясным. Не пытайтесь запомнить правила приоритета, так как однажды вы в конечном итоге будете использовать другой язык, который немного отличается от них, и вы запутаетесь. Или старый и в конечном итоге забываешь, что имеет более высокий приоритет (как я делаю с * и ->).

    Попытайтесь запомнить правила приоритета, поскольку однажды вы в конечном итоге будете использовать другой язык, в котором они будут немного отличаться, и вы запутаетесь. Или старый и в конечном итоге забываешь, что имеет более высокий приоритет (как я делаю с * и ->).

    Попытайтесь запомнить правила приоритета, поскольку однажды вы в конечном итоге будете использовать другой язык, в котором они будут немного отличаться, и вы запутаетесь. Или старый и в конечном итоге забываешь, что имеет более высокий приоритет (как я делаю с * и ->).

    3
    ответ дан 7 November 2019 в 09:46
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: