Разъяснение о приоритетности операторов - PullRequest
0 голосов
/ 24 марта 2019

Я получил этот фрагмент из некоторых упражнений и вопроса: что является результатом следующего кода:

main()
{
    char *p = "ayqm";
    printf("%c", ++*(p++));
}

Мой ожидаемый ответ был z, но фактический ответ был на самом деле b.Как это возможно?

Позднее редактирование: фрагмент взят из упражнения и не фокусируется на проблемах строкового литерала или синтаксиса, существующих за пределами кодовой зоны printf().

Ответы [ 2 ]

2 голосов
/ 24 марта 2019

Как сообщалось, программа имеет несколько проблем:

  • она пытается изменить строковую константу "ayqm", которая описана как неопределенное поведение в стандарте C.
  • он использует printf без надлежащего объявления, снова вызывая неопределенное поведение.
  • его вывод не завершается символом новой строки, вызывая поведение, определяемое реализацией.
  • прототип для main без возвращаемого типа является устаревшим, больше не поддерживается стандартом C.
  • инкрементные символы создают поведение, определяемое реализацией.Если набор символов выполнения ASCII, 'a'+1 производит 'b', но это не гарантируется стандартом C.Действительно, в наборе символов EBCDIC, все еще используемом в старых компьютерах мэйнфреймов, буквы находятся в одной монотонной последовательности (например: 'a'+1 == 'b', но 'i'+1 != 'j' в этом наборе символов).

Вот исправленная версия:

#include <stdio.h>

int main(void) {
    char str[] = "ayqm";
    char *p = str;
    printf("%c\n", ++*(p++));
    return 0;
}

p является постинкрементным, что означает, что текущее значение p используется для оператора *, а значение p увеличивается до следующей точки последовательности, а именновызов функции printf.Символ, считываемый через p, 'a', затем увеличивается, что может давать или не давать 'b' в зависимости от набора символов выполнения.

После того, как printf вернется к функции main, p указывает на str[1], а str содержит строку "byqm".

2 голосов
/ 24 марта 2019

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

Указатель p указывает на строковый литерал "ayqm".Это выражение

printf ("%c", ++*(p++));

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

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

...