Использование `volatile` приводит к неожиданным результатам

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

#include <memory>
#include <string>
#include <iostream>


int main() {
    std::string s = "Hi\n";
    std::cout << s;

    auto p = std::make_unique<const char *>(s.c_str());
    std::cout << *(p.get());

    return 0;
}

Он печатает

Hi
Hi

Но добавление одного ключевого слова volatile:

#include <memory>
#include <string>
#include <iostream>


int main() {
    std::string s = "Hi\n";
    std::cout << s;

    auto p = std::make_unique<volatile const char *>(s.c_str());
    std::cout << *(p.get());

    return 0;
}

заставляет его печатать:

Hi
1

Это тоже не помогло:

#include <memory>
#include <string>
#include <iostream>


int main() {
    std::string s = "Hi\n";
    std::cout << s;

    auto p = std::make_unique<volatile const char *>(reinterpret_cast<volatile const char *>(s.c_str()));
    std::cout << *(p.get());

    return 0;
}

Почему?

Просто добавить его без особой причины? Я предполагаю, что средство форматирования думает, что это нечто иное, чем строка C.

tadman 12.07.2023 17:32
std::ostream имеет перегрузку для operator << для const char* и bool (указатель имеет преобразование в bool), а не для volatile const char *
Jarod42 12.07.2023 17:34
volatile имеет очень мало применений. Я сомневаюсь, что ваша исходная проблема нуждается в volatile.
Jarod42 12.07.2023 17:37

Спасибо, @ Jarod42, это действительно так, как показала моя проверка ваших гипотез здесь. Исходная ошибка может быть связана или не связана с использованием volatile, а volatile используется из-за факта использования переменной во встроенной системе. Исходная ошибка, скорее всего, связана с использованием интеллектуальных указателей.

Roman Pavelka 12.07.2023 17:37

пожалуйста, не добавляйте ответ на вопрос. Вместо этого вы должны опубликовать это как ответ. Вы даже можете принять свой собственный ответ.

463035818_is_not_an_ai 12.07.2023 17:46

Остерегайтесь, что вы ставите unique_ptr предмет, которым вы не владеете. std::string имеет уникальное право собственности на данные указанного символа и не передает это право unique_ptr. Вы получите Undefined Behavior из-за двойной delete или аналогичной двойной очистки в конце области.

François Andrieux 12.07.2023 17:47

@ 463035818_is_not_an_ai Чувствовалось бы, что я присвоил себе ответ Jarod42.

Roman Pavelka 12.07.2023 17:48

@RomanPavelka Если бы их это заботило, они бы вместо этого разместили комментарий в качестве ответа.

François Andrieux 12.07.2023 17:48

они дали свой комментарий. С ним можно делать что угодно ;)

463035818_is_not_an_ai 12.07.2023 17:49

просто добавьте ссылку на комментарий, и все в порядке. Что-то вроде "Как указал Джарод в комментарии..."

463035818_is_not_an_ai 12.07.2023 17:49

Оффтопик: std::make_unique<const char *> уже кодмелл?

Marek R 12.07.2023 18:54

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

Marek R 12.07.2023 19:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
12
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ответ в комментарии от Jarod42:

std::ostream имеет перегрузку для оператора << для const char* и bool (указатель имеет преобразование в bool), но не для volatile const char *

Затем разницу можно воспроизвести просто:

#include <iostream>

int main() {
    /*volatile*/ const char * s = "abc\n";
    std::cout << s;

    return 0;
}

Дает abc с закомментированным volatile и 1 (без новой строки) с раскомментированием.

Для справки оператор << и оператор <<. Таким образом, в С++ 23 адрес будет напечатан вместо 1 для volatile случая.

Jarod42 12.07.2023 18:12

Хорошая демонстрация: cppinsights показывает, что для обоих случаев выбрана разная перегрузка оператора.

Marek R 12.07.2023 19:06

Другие вопросы по теме