С Новым годом! Форум программистов, компьютерный форум, киберфорум
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. Показов 16558. Ответов 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
Ответ Создать тему
Новые блоги и статьи
изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru