Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.51/88: Рейтинг темы: голосов - 88, средняя оценка - 4.51
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30

[Задача] const volatile

27.05.2011, 15:53. Показов 16594. Ответов 29

Студворк — интернет-сервис помощи студентам
Предполагаю, что читатель значет, что такое const и volatile. Но не факт, что все знают, как они влияют на генерацию кода компилятором. И можно это пояснить на которких примерах

1. Модификатор const

C
1
2
3
4
5
6
7
8
9
10
11
extern int iii;
extern int xxx;
extern int yyy;
extern int *ppp;
 
void func (void)
{
  xxx = iii;
  *ppp = 777;
  yyy = iii;
}
Code
1
2
3
4
5
6
7
8
9
10
11
$ gcc -O2 t.c -S
$ cat t.s
        movl    iii, %eax
        pushl   %ebp
        movl    %esp, %ebp
        movl    %eax, xxx
        movl    ppp, %eax
        movl    $777, (%eax)
        movl    iii, %eax
        popl    %ebp
        movl    %eax, yyy
По коду видим, что у нас имеется следующий порядок действий: прочитали iii на регистр, результат записали в xxx. Прочитали значение ppp, по указателю записали 777. Ещё раз прочитали iii на регистр, записали результат в yyy. Мы видим, что значение iii из памяти читается два раза. И происходит это потому, что у нас имеется запись по указателю, который указывает неизвестно куда и может в том числе испортить значение iii.

Теперь пометим iii модификатором const и посмотрим на код

C
1
2
3
4
5
6
7
8
9
10
11
extern const int iii;
extern int xxx;
extern int yyy;
extern int *ppp;
 
void func (void)
{
  xxx = iii;
  *ppp = 777;
  yyy = iii;
}
Code
1
2
3
4
5
6
7
8
9
10
$ gcc -O2 t.c -S
$ cat t.s
        movl    iii, %edx
        movl    ppp, %eax
        pushl   %ebp
        movl    %esp, %ebp
        movl    %edx, xxx
        movl    $777, (%eax)
        popl    %ebp
        movl    %edx, yyy
Здесь мы видим, что значение iii из памяти прочитано только один раз. В xxx и yyy записывается одно и то же значение %edx. Собственно, это и есть то, как влияет модификатор const на генерацию кода (а точнее, один из случаев).

2. Модификатор volatile

C
1
2
3
4
5
6
7
8
9
extern int iii;
extern int xxx;
extern int yyy;
 
void func (void)
{
  xxx = iii;
  yyy = iii;
}
Code
1
2
3
4
5
6
7
8
$ gcc -O2 t.c -S
$ cat t.s
        pushl   %ebp
        movl    iii, %eax
        movl    %esp, %ebp
        popl    %ebp
        movl    %eax, xxx
        movl    %eax, yyy
Здесь мы видим, что компилятор только один раз прочёл из памяти переменную iii, потому как между двумя точками использования этого значения нету записей в память, которые могли бы конфликтовать с iii (т.е. которые могли бы затереть iii).

Теперь добавим модификатор volatile

C
1
2
3
4
5
6
7
8
9
extern volatile int iii;
extern int xxx;
extern int yyy;
 
void func (void)
{
  xxx = iii;
  yyy = iii;
}
Code
1
2
3
4
5
6
7
8
9
$ gcc -O2 t.c -S
$ cat t.s
        movl    iii, %eax
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        movl    %eax, xxx
        movl    iii, %eax
        movl    %eax, yyy
Видим, что переменная iii читается уже два раза. Потому что модификатор volatile говорит о том, что переменная может измениться невидимым для компилятора образом.

Внимание вопрос.

Что по ваему мнению означает переменная, описанная как

C
1
extern volatile const int iii;
Модификатор const с одной стороны говорит о том, что переменная не может изменяться, но с другой стороны модификатор volatile означает, что переменная может изменяться неявным для компилятора образом. Поиском желательно не пользоваться, а попробовать догадаться самому
11
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.05.2011, 15:53
Ответы с готовыми решениями:

И снова volatile. Глобальный массив, изменяемый в обработчике прерывания, должен быть volatile?
Всем привет. Имеется официальный код примера на чип-трансивер nrf24LE1 от Nordic. Keil C51 // Global variables uint8_t...

const volatile
Пример из Шилдт Г. "С++ Базовый курс (3-е издание, 2010)" стр 205 const volatile unsigned char *port = (const volatile char *)...

const_cast: const и volatile
Как известно const_cast сбрасывает наложенные ограничения при помощи модификаторов const и volatile. Как мне стало известно volatile -...

29
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
27.05.2011, 17:14
Цитата Сообщение от Evg Посмотреть сообщение
Что по ваему мнению означает переменная, описанная как
Читал про это когда-то, но за ненадобностью забыл) Поэтому полез в гугл (ответ выкладывать не буду, какой смысл)). Но пока гуглил вот, что нарыл:
вопрос почему эта программа, будучи откомпилированной в Студии, печатает "1" вместо "0", озадачивает даже опытных программистов на С++ (или по крайней мере они дают неправильное объяснение причины происходящего).

C++
1
2
3
4
5
6
#include <iostream>
volatile const char* p = "0";
int main() {
  std::cout << p << std::endl;
  return 0;
}
Для получение схожего эффекта в GCC надо заменить "0" на "false".
Думаю вопрос по теме)
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
27.05.2011, 23:38  [ТС]
Цитата Сообщение от Kastaneda Посмотреть сообщение
Для получение схожего эффекта в GCC надо заменить "0" на "false"
У меня в gcc печатается "1"
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
28.05.2011, 11:37
Лучший ответ Сообщение было отмечено как решение

Решение

В общем там, где я это нарыл, объяснение было такое: нет перегруженной версии operator<<() для
volatile const char*, поэтому требуется приведение типа. К const char* компилятор привести не может (ибо volatile), как и к volatile char* (ибо const), поэтому (как там написанно) согласно стандарту указатель приводиться к bool*.

По поводу стандарта не знаю, я с ним не дружу в силу плохого английского.
Вот решил проверить вышенаписанное.
Итак - MSVS
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
;std::cout << p << std::endl;
00D513BE  mov         esi,esp  
00D513C0  mov         eax,dword ptr [__imp_std::endl (0D582A0h)]  
00D513C5  push        eax  
00D513C6  cmp         dword ptr [p (0D57000h)],0 ;сравниваем  4 байта, расположенных по указателю p, с нулем
00D513CD  setne       cl  ;если в результате сравнения не выставлен ZF (флаг нуля), то устанавливаем cl в 1, если выставлен ZF, то cl будет 0
00D513D0  mov         edi,esp  
00D513D2  movzx       edx,cl  ;заносим cl в edx, заполняя старшие разряды нулями
00D513D5  push        edx  ;пихаем edx в стек, для вызова operator<< 
00D513D6  mov         ecx,dword ptr [__imp_std::cout (0D58298h)]  
00D513DC  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D5829Ch)]  
00D513E2  cmp         edi,esp  
00D513E4  call        @ILT+310(__RTC_CheckEsp) (0D5113Bh)  
00D513E9  mov         ecx,eax  
00D513EB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D58294h)]  
00D513F1  cmp         esi,esp  
00D513F3  call        @ILT+310(__RTC_CheckEsp) (0D5113Bh)
Для тех, кто не знает синтаксиса Intel, добавил коментарии к основным моментам. Из листинга видно, что указатель действильно интерпритируется как bool*, и независимо от того, на что он указывает, будет выведено 1 . Т.е. такой код:
C++
1
2
3
4
5
6
7
#include <iostream>
volatile const char* p = "blablabla";
int main() {
    char a=*p;
  std::cout << p << std::endl;
  return 0;
}
привет к аналогичному результату.
Дальше - в пояснении сказано, что в GCC для достижение такого же результата нужно заменить "0" на "false". Но ведь если, как там говориться, volatile const char* приводится к bool* согласно стандарту, а g++, как мы знаем, более дружен со стандартом, чем компилятор Intel, то разницы быть не должно. Смотрим:
Во первых выводится 1 при *p="0" (ну и естественно при *p="false"), собственно как я и ожидал. Смотрим, что там внутри:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
00401326    mov    0x46e000,%eax
0040132B    test   %eax,%eax
0040132D    setne  %al
00401330    movzbl %al,%eax
00401333    mov    %eax,0x4(%esp)
00401337    movl   $0x4740c0,(%esp)
0040133E    call   0x448558 <std::ostream::operator<<(bool)>
00401343    movl   $0x467508,0x4(%esp)
0040134B    mov    %eax,(%esp)
0040134E    call   0x4482ec <std::ostream::operator<<(std::ostream& (*)(std::ostream&))>
00401353    mov    $0x0,%eax
00401358    leave
00401359    ret
К сожалению я не знаю синтаксиса AT&T, но интуитивно понятно, что
Assembler
1
2
3
mov    0x46e000,%eax
0040132B    test   %eax,%eax
0040132D    setne  %al
после test %eax,%eax, результат просто не может быть 0 (мы видим, что eax= 0x46e000), поэтому al будет по-любому 1 (странно что этот код вообще не выкинут). И еще я не вижу ни одного push'а перед вызовом <std::ostream::operator<<(bool)> (кстати - все таки bool !)). Вобщем не понял я этот код до конца, но по-моему, реализация несколько иная, хотя и результат тот же.

Добавлено через 4 минуты
Цитата Сообщение от Kastaneda Посмотреть сообщение
И еще я не вижу ни одного push'а перед вызовом <std::ostream::operator<<(bool)>
Нашел)):
Assembler
1
2
00401330        movzbl %al,%eax
00401333        mov    %eax,0x4(%esp)
Добавлено через 15 минут
Почитал про синтаксис AT&T, инструкция
Assembler
1
mov    0x46e000,%eax
аналогична
Assembler
1
mov         eax,dword ptr [46e000h]
т.е. занесения значения по адресу в регистр (очевидно, что 0x46e000 - это содержание указателя p), по сему можно сказать, что компиляторы Intel и g++ в данном случае генерируют подобные коды.

Не по теме:

осталость добавить как в лабораторных пишут:"опытным путем было установленно, что указатель volatile const char* компилятор приведет к bool*":D

4
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
28.05.2011, 13:59
Цитата Сообщение от Kastaneda Посмотреть сообщение

Не по теме:

осталость добавить как в лабораторных пишут:"опытным путем было установленно, что указатель volatile const char* компилятор приведет к bool*":D

Вот за подобный идиотизм С++ мне жутко не нравится. ИМХО ВСЕ преобразования типа должны делаться явно. Возможно, кроме целое -> дробное.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.05.2011, 22:16  [ТС]
Цитата Сообщение от Kastaneda Посмотреть сообщение
согласно стандарту указатель приводиться к bool*
Всегда чувствовал, что курили не только разработчики Си, но и Си++

По поводу того, что же такое const volatile
В конструкции const volatile модификатор const относится только к языковой части, но не к аппаратной. Т.е. переменную const volatile программист не имеет права менять (компилятор будет ругаться), но аппаратура значение переменной может изменить. Т.е. volatile - это переменная, которую можно программно читать и писать (типа порта ввода-вывода), а const volatile - это переменная, которую программно можно только читать (что-то типа таймера)
2
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.06.2011, 16:31  [ТС]
Цитата Сообщение от Kastaneda Посмотреть сообщение
согласно стандарту указатель приводиться к bool*
Поясни, почему печатается 1? Ведь должно напечататься значение указателя (адрес), а не значение по разыменованному указателю

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
bool val = 1;
bool *p = &val;
 
int main (void)
{
  std::cout << p << std::endl;
  return 0;
}
Code
1
2
3
$ g++ t.cc
$ ./a.out
0x804a030
Добавлено через 15 минут
Мне более понятна система команд sparc, а потому вот код, полученный на sparc'овском gcc:

Code
1
2
3
4
5
6
7
    sethi   %hi(p), %g1
    ld  [%g1+%lo(p)], %g2
    subcc   %g0, %g2, %g0
    sethi   %hi(_ZSt4cout), %o0
    addx    %g0, 0, %o1
    call    _ZNSolsEb, 0
     or %o0, %lo(_ZSt4cout), %o0
здесь читается значение p, далее в регистре %o1 формируется значение (p == 0 ? 0 : 1). Т.е. по сути делается преобразование pointer->bool (но не bool*). Регистр %o1 является параметром вызова процедуры _ZNSolsEb, которая есть

Code
1
2
$ c++filt _ZNSolsEb
std::basic_ostream<char, std::char_traits<char> >::operator<<(bool)
Т.е. в данном случае указатель реально преобразуется к bool (а не к указателю на bool, как ты писал выше). Ты опечатался или тут всё-таки какое-то другое пояснение?

Добавлено через 2 минуты
Цитата Сообщение от Kastaneda Посмотреть сообщение
Дальше - в пояснении сказано, что в GCC для достижение такого же результата нужно заменить "0" на "false"
Если смотреть на код gcc, то единственный случай, когда напечатается 0 - это когда указатель проинициализировать NULL'ом (или оставить без инициализации, что есть то же самое). Т.е. что написано в кавычках - роли не играет
1
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
01.06.2011, 18:01
Цитата Сообщение от Evg Посмотреть сообщение
Т.е. в данном случае указатель реально преобразуется к bool (а не к указателю на bool, как ты писал выше). Ты опечатался или тут всё-таки какое-то другое пояснение?
Нет, я не опечатался, но судя по :
в GCC для достижение такого же результата нужно заменить "0" на "false"
человек не совсем понимал о чем писал.

Цитата Сообщение от Evg Посмотреть сообщение
Т.е. по сути делается преобразование pointer->bool (но не bool*)
Ага, я сейчас на Intel'овский код еще раз посмотрел, там сравнивается значение по адресу указателя с нулем (а не по адресу, который содержит указатель, как я подумал (лучше б студия показывала код без своих пояснений)). Т.е. дествительно приводится к bool, а не к bool*.

И вот еще что - скомпилировал такой код в MSVS:
C++
1
2
3
4
5
6
#include <iostream>
volatile const char* p=NULL;
int main() {
  std::cout <<p<< std::endl;
  return 0;
}
на что студия услужливо предупредила:
warning C4800: volatile const char *: принудительно задано логическое значение "true" или "false" (предупреждение о производительности)
Вот, разобрались)

Добавлено через 2 минуты
Цитата Сообщение от Evg Посмотреть сообщение
Мне более понятна система команд sparc
Evg, а где применяется этот sparc?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
01.06.2011, 20:25  [ТС]
Цитата Сообщение от Kastaneda Посмотреть сообщение
Вот, разобрались)
Я бы сказал, экспериментально выяснили, что делается по факту. Но я так толком и не понял, почему делается так. Я поначалу думал, что ты что-то близкое к стандарту процитировал, но, как оказывается, это тоже были чьи-то домыслы?

Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, а где применяется этот sparc?
Там, где надёжность машин на intel'овских процессорах не устраивает
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
01.06.2011, 20:43
Цитата Сообщение от Evg Посмотреть сообщение
Я поначалу думал, что ты что-то близкое к стандарту процитировал, но, как оказывается, это тоже были чьи-то домыслы?
Так я же сразу написал:

Цитата Сообщение от Kastaneda Посмотреть сообщение
В общем там, где я это нарыл, объяснение было такое: нет перегруженной версии operator<<() для
volatile const char*, поэтому требуется приведение типа. К const char* компилятор привести не может (ибо volatile), как и к volatile char* (ибо const), поэтому (как там написанно) согласно стандарту указатель приводиться к bool*.
А по поводу стандарта вот:
Цитата Сообщение от Kastaneda Посмотреть сообщение
По поводу стандарта не знаю, я с ним не дружу в силу плохого английского.
Но если (как минимум) 2 компилятора создали подобные коды, то можно предположить, что есть какое-то оговоренное поведение для данного случая.
0
01.06.2011, 23:08

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
Но если (как минимум) 2 компилятора создали подобные коды, то можно предположить, что есть какое-то оговоренное поведение для данного случая
Вряд-ли на это можно полагаться. Например (насколько мне известно) в стандарте никак не оговаривается, как должны быть реализованы виртуальные функции, однако все (по крайней мере известные мне) компиляторы реализуют их через таблицу указателей на функции.

0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
02.06.2011, 11:14
Лучший ответ Сообщение было отмечено как решение

Решение

Порылся в стандарте, т.к. с английским совсем туго, то понял я не много, но суть, вроде как, уловил.
Вобщем нет четкого определения, что volatile const char* при случае будет приведен к bool, но там описана некая схема приведения типов (что-то типа иерархии (conversion rank)). На сколько я понял (не факт, что правильно) в случае, когда по какой-либо причине невозможно приведение к конктретному типу, то приведение осуществляется согласно этому conversion rank. Суть в том, что одни типы имеют более высокий rank, чем другие. Т.е. сначала пробуем превести к типу, имеющему самый низкий rank, если это невозможно, значит двигаемся выше и пробуем превести к слещующему типу. И, как я понял, bool является первым возможным типом для volatile const char*, поэтому к нему и приводится.
Может кто-то поправит?
4
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
02.06.2011, 15:39
В Страуструпе написано :

Указатель можно неявно преобразовать к bool. Ненулевой указатель принимает значение true, нулевой false.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
02.06.2011, 15:47
ForEveR, по-моему здесь подразумевается несколько иное.
"можно неявно преобразовать" т.е. использовать указатель в таком виде:
C++
1
2
if(ptr)
//some code
1
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
02.06.2011, 16:12
Kastaneda, М. Не буду спорить. Скорее всего про это и написано.
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
02.06.2011, 16:17
ForEveR, просто в случае с if вполне законно неявно привести указатель к bool, а вот в случае с std::cout как-то не вяжется...
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
02.06.2011, 16:57
А так еще веселее..

C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <typeinfo>
 
static volatile const char* const ptr = "blablabla";
 
int main()
{
    std::cout << typeid(ptr).name() << '\n';
    std::cout << ptr << '\n';
    std::cout << (const volatile void*) ptr << '\n';
}
Выходит любой cv pointer приводится к bool

Добавлено через 4 минуты
Веселимся)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <typeinfo>
#include <vector>
 
static volatile const char* const ptr = "blablabla";
 
int main()
{
    std::cout << typeid(ptr).name() << '\n';
    std::cout << ptr << '\n';
    std::cout << (const volatile void*) ptr << '\n';
    std::cout << (const volatile int*) ptr << '\n';
    std::cout << (const volatile bool*) ptr << '\n';
    std::cout << (const volatile long*) ptr << '\n';
    std::cout << (const volatile wchar_t*) ptr << '\n';
    std::cout << (const volatile double*) ptr << '\n';
    std::cout << (const volatile long long*) ptr << '\n';
    std::cout << (const volatile std::vector<char>*) ptr << '\n';
    std::cout << (const volatile std::string*) ptr << '\n';
    std::cout << reinterpret_cast<const volatile std::vector<std::vector<int> >*>(ptr) << '\n';
}
Добавлено через 9 минут
Собственно

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
volatile const char* ptr = "blablabla";
 
std::ostream& operator <<(std::ostream& os, volatile const char* ptr)
{
    os << (char*)ptr << std::endl;
    return os;
}
 
int main()
{
    std::cout << typeid(ptr).name() << '\n';
    std::cout << ptr << '\n';
    fprintf(stderr, "%p\n", ptr);
}
Добавлено через 2 минуты
Ну или так. Вообщем просто нет подходящего оператора.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
volatile const char* ptr = "blablabla";
 
template<class T>
std::ostream& operator <<(std::ostream& os, volatile const T* ptr)
{
    os << (T*)ptr << std::endl;
    return os;
}
 
int main()
{
    std::cout << typeid(ptr).name() << '\n';
    std::cout << ptr << '\n';
    std::cout << (volatile const void*) ptr << '\n';
}
0
Higher
 Аватар для diagon
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
06.10.2012, 22:43
Пардоньте за некропостинг, но
Цитата Сообщение от Kastaneda Посмотреть сообщение
В общем там, где я это нарыл, объяснение было такое: нет перегруженной версии operator<<() для
volatile const char*, поэтому требуется приведение типа. К const char* компилятор привести не может (ибо volatile), как и к volatile char* (ибо const), поэтому (как там написанно) согласно стандарту указатель приводиться к bool*.
тут очень много ереси >_<

0) в данном примере можно убрать const, дальше я буду считать, что там просто volatile
1) наиболее приоритетные перегрузки оператора << принимают const char* либо char *, однако они не подходят(volatile T не может неявно привестись к T, где T - какой-либо тип. Для const и const volatile это правило также справедливо.).
2) следующая возможная перегрузка принимает void*, однако указатели, помеченные как const либо volatile не могут неявно привестись к void*.
3) следующая по приоритету перегрузка принимает bool, который и становится окончательным вариантом.
0
 Аватар для alkagolik
1599 / 622 / 113
Регистрация: 15.07.2011
Сообщений: 3,548
07.10.2012, 01:16
Цитата Сообщение от Evg Посмотреть сообщение
Внимание вопрос.
специально тему не читал. Попытаюсь взять "с наскока". const не будет влиять на оптимизацию, а всего лишь пометит память как read-only. volatile скажет "всегда читать значение из памяти". В итоге получится бессмысленная конструкция "всегда читать из памяти данные, данные изменять запрещено". Такой себе писсимизатор (как антоним оптимизатору).

Добавлено через 4 минуты
упс, некропост.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
07.10.2012, 09:50
Цитата Сообщение от diagon Посмотреть сообщение
тут очень много ереси >_<
0) в данном примере можно убрать const, дальше я буду считать, что там просто volatile
1) наиболее приоритетные перегрузки оператора << принимают const char* либо char *, однако они не подходят(volatile T не может неявно привестись к T, где T - какой-либо тип. Для const и const volatile это правило также справедливо.).
2) следующая возможная перегрузка принимает void*, однако указатели, помеченные как const либо volatile не могут неявно привестись к void*.
3) следующая по приоритету перегрузка принимает bool, который и становится окончательным вариантом.
Так я же тоже самое писал выше:

Цитата Сообщение от Kastaneda Посмотреть сообщение
Порылся в стандарте, т.к. с английским совсем туго, то понял я не много, но суть, вроде как, уловил.
Вобщем нет четкого определения, что volatile const char* при случае будет приведен к bool, но там описана некая схема приведения типов (что-то типа иерархии (conversion rank)). На сколько я понял (не факт, что правильно) в случае, когда по какой-либо причине невозможно приведение к конктретному типу, то приведение осуществляется согласно этому conversion rank. Суть в том, что одни типы имеют более высокий rank, чем другие. Т.е. сначала пробуем превести к типу, имеющему самый низкий rank, если это невозможно, значит двигаемся выше и пробуем превести к слещующему типу. И, как я понял, bool является первым возможным типом для volatile const char*, поэтому к нему и приводится.
Может кто-то поправит?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.10.2012, 09:50
Помогаю со студенческими работами здесь

Заменить volatile на Thread.MemoryBarrier. Код приведён. Как оптимизировать обращения для чтения к volatile полю класса?
Не совсем понятна мне пока что работа Thread.MemoryBarrier. Знаю, что можно оптимизировать обращения к полю _cancellation, смотрел...

int const * const foo(const int* param) const - разъясните значение квалификаторов
int const * const foo(const int* param) const -----1------2----------3----------------4 1: ? 2: делает содержимое массива или...

int\ volatile int \ const int
Товарищи, паника! Имеется код: int a = 5; std::cout &lt;&lt; &quot;Init value a: &quot; &lt;&lt; a &lt;&lt; &quot;\n&quot;; int *p; p = (int*) &amp;a; *p = 0; ...

char operator[](unsigned short offset) const; // что означает const?
Собстенно вопрос уже озвучен :).

Что это bool operator== (const CLASS&) const;
Что это? class CLASS { public: bool operator== (const CLASS&amp;) const; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru