Я не понимаю, как мой компилятор получил этот вывод - PullRequest
0 голосов
/ 12 октября 2019

Обратите внимание, что я использую компилятор Turbo C ++, потому что мы должны изучать только Turbo C ++ для нашей школьной программы. Вот почему в этом случае оператор cout вычисляется справа налево.

Программа

#include <iostream.h>
#include <string.h>

void func(char *s, char t[]) {
    strcpy(t, "Have fun");
    s = "Be\0Cool";
    cout << s[0] << ++s << s++ << --s << strupr(s+2) << ++s << s++ << s;
}

int main() {
    char x[] = "Hello World!!!", y[] = "Hello World";
    func(x, y);
    cout << x << y;
    return 0;
}

Выход

CCOOLeeOOLBeBeHello World !!! Веселитесь


Я чувствую, что результат должен быть:

C Cool eeOOLBeBeHello World !!! Веселитесь

Поскольку в ++s части оператора cout (вторая позиция) указатель находится в индексе 3 строки s, поэтому следует печатать только «Cool». Вместо этого «COOL» печатается. Почему это происходит?

1 Ответ

1 голос
/ 12 октября 2019

Тесты с Visual Studio 2019

Для сравнения, в Visual Studio 2019 (DEBUG), если мы внесем необходимые изменения для компиляции кода, произойдет сбой программы, потому что мы пытаемсяизменить постоянную строку ("Be\0Cool").

Если мы сделаем дополнительные изменения, чтобы избежать сбоя (используя локальный массив), вы получите:

CCoOLeCoOLOLCoOLBeCoOLHello World !!! Веселитесь

Если мы разделим cout << s[]…; линию на несколько вызовов на cout (по одному перед каждым <<), то получится:

BeeeCOOLCOOLHello World !!! Веселитесь

Или, если мы добавим строку после каждого вывода, мы получим:

B
e
e
e
COOL


COOL
Hello World!!!
Have fun

Попытка понять вывод Turbo C ++

Если мызатем обращаем каждый вызов к cout, чтобы начать с последнего (т.е. cout << s<< endl;) и завершить первым (cout << s[0] << endl), тогда мы получим:

Be
Be

OOL
e
e
COOL
C
Hello World!!!
Have fun

Если мы напишем это вручную, начиная с третьего последнегострока и вверх, а затем две последние строки по порядку без пробелов, мы получаем:

CCOOLeeOOLBeBeHello World !!! Веселитесь

Что именно вы получили какoutput.

Таким образом, представляется, что Turbo C ++ оценивает каждое выражение справа налево.

Примечаниятребуемые изменения для компиляции (и запуска)

  • <iostream.h> недоступны, поэтому я должен использовать <iostream> вместо этого.
  • #define _CRT_SECURE_NO_WARNINGS должен быть добавлен сверхупотому что некоторые функции небезопасны (и не будут компилироваться по умолчанию).
  • using namespace std;, чтобы избежать внесения дополнительных изменений в код.
  • Добавьте приведение в s = (char *)"Be\0Cool";, чтобы компилировать строки,
    • Это приводит к сбою, поскольку данные постоянны, и мы пытаемся их изменить.
  • Удалите приведение и вместо этого напишите char data[] = "Be\0Cool"; s = data;
    • программа запускается, но вывод CCoOLeCoOLOLCoOLBeCoOLHello World!!!Have fun
    • На самом деле это неопределенное поведение. Это просто фактический результат.

Неопределенное поведение

Некоторые вещи не определены стандартом и, следовательно, не определеныТребуется работать определенным образом. Что ж, как и следовало ожидать, если постоянная память не поддерживается, она работает как память для чтения и записи.

Для порядка оценки распространены следующие возможности:

  • слева направо
  • справа налево
  • что является более оптимальным

Кроме того, поскольку переменная изменяется более одного раза, значение s не определяется во время оценки и после нее. Легко запомнить правило состоит в том, чтобы избегать изменения одной и той же переменной более одного раза в одном выражении.

About strupr

Эта функция изменяет строку до завершающего нуляхарактер. В вашем случае он будет преобразовывать в верхний регистр все буквы из любого значения, которое s имеет в момент вызова.

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