С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.81/75: Рейтинг темы: голосов - 75, средняя оценка - 4.81
Evg
Эксперт CАвтор FAQ
19361 / 7210 / 538
Регистрация: 30.03.2009
Сообщений: 20,161
Записей в блоге: 30
1

[Задача] const volatile

27.05.2011, 15:53. Просмотров 13550. Ответов 25

Предполагаю, что читатель значет, что такое 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;
}
Код
$ 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;
}
Код
$ 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;
}
Код
$ 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;
}
Код
$ 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 означает, что переменная может изменяться неявным для компилятора образом. Поиском желательно не пользоваться, а попробовать догадаться самому
10
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.05.2011, 15:53
Ответы с готовыми решениями:

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

Что такое void и volatile?
Всем привет :) Уже 2 недели по немного изучаю С по книге Герберта Шилдта....

директива #pragma. модификатор volatile. и функция system()
Всем привет! Скажите пожалуйста что делает директива #pragma Я знаю, что её...

CONST_RETURN char *__cdecl strstr (const char *_Str, const char *_SubStr)
#include <stdio.h> #include <string.h> char tracks = { "ya ostavil svoe...

#define и const
В чем их различия? Делая тест по подготовке к ЕГЭ, в заданиях части С были...

25
Kastaneda
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
27.05.2011, 17:14 2
Цитата Сообщение от 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
19361 / 7210 / 538
Регистрация: 30.03.2009
Сообщений: 20,161
Записей в блоге: 30
27.05.2011, 23:38  [ТС] 3
Цитата Сообщение от Kastaneda Посмотреть сообщение
Для получение схожего эффекта в GCC надо заменить "0" на "false"
У меня в gcc печатается "1"
0
Kastaneda
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
28.05.2011, 11:37 4
Лучший ответ Сообщение было отмечено как решение

Решение

В общем там, где я это нарыл, объяснение было такое: нет перегруженной версии 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
ValeryLaptev
Эксперт С++
1052 / 831 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
28.05.2011, 13:59 5
Цитата Сообщение от Kastaneda Посмотреть сообщение

Не по теме:

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

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

По поводу того, что же такое const volatile
В конструкции const volatile модификатор const относится только к языковой части, но не к аппаратной. Т.е. переменную const volatile программист не имеет права менять (компилятор будет ругаться), но аппаратура значение переменной может изменить. Т.е. volatile - это переменная, которую можно программно читать и писать (типа порта ввода-вывода), а const volatile - это переменная, которую программно можно только читать (что-то типа таймера)
2
Evg
Эксперт CАвтор FAQ
19361 / 7210 / 538
Регистрация: 30.03.2009
Сообщений: 20,161
Записей в блоге: 30
01.06.2011, 16:31  [ТС] 7
Цитата Сообщение от 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;
}
Код
$ g++ t.cc
$ ./a.out
0x804a030
Добавлено через 15 минут
Мне более понятна система команд sparc, а потому вот код, полученный на sparc'овском gcc:

Код
	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, которая есть

Код
$ 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
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
01.06.2011, 18:01 8
Цитата Сообщение от 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
19361 / 7210 / 538
Регистрация: 30.03.2009
Сообщений: 20,161
Записей в блоге: 30
01.06.2011, 20:25  [ТС] 9
Цитата Сообщение от Kastaneda Посмотреть сообщение
Вот, разобрались)
Я бы сказал, экспериментально выяснили, что делается по факту. Но я так толком и не понял, почему делается так. Я поначалу думал, что ты что-то близкое к стандарту процитировал, но, как оказывается, это тоже были чьи-то домыслы?

Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, а где применяется этот sparc?
Там, где надёжность машин на intel'овских процессорах не устраивает
0
Kastaneda
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
01.06.2011, 20:43 10
Цитата Сообщение от Evg Посмотреть сообщение
Я поначалу думал, что ты что-то близкое к стандарту процитировал, но, как оказывается, это тоже были чьи-то домыслы?
Так я же сразу написал:

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

Не по теме:

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

0
Kastaneda
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
02.06.2011, 11:14 12
Лучший ответ Сообщение было отмечено как решение

Решение

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

Указатель можно неявно преобразовать к bool. Ненулевой указатель принимает значение true, нулевой false.
0
Kastaneda
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
02.06.2011, 15:47 14
ForEveR, по-моему здесь подразумевается несколько иное.
"можно неявно преобразовать" т.е. использовать указатель в таком виде:
C++
1
2
if(ptr)
//some code
1
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
02.06.2011, 16:12 15
Kastaneda, М. Не буду спорить. Скорее всего про это и написано.
0
silent_1991
Эксперт С++
5011 / 3071 / 271
Регистрация: 11.11.2009
Сообщений: 7,045
Завершенные тесты: 1
02.06.2011, 16:17 16
ForEveR, просто в случае с if вполне законно неявно привести указатель к bool, а вот в случае с std::cout как-то не вяжется...
0
ForEveR
В астрале
Эксперт С++
7997 / 4755 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
02.06.2011, 16:57 17
А так еще веселее..

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
diagon
Higher
1937 / 1203 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
06.10.2012, 22:43 18
Пардоньте за некропостинг, но
Цитата Сообщение от 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
Заблокирован
07.10.2012, 01:16 19
Цитата Сообщение от Evg Посмотреть сообщение
Внимание вопрос.
специально тему не читал. Попытаюсь взять "с наскока". const не будет влиять на оптимизацию, а всего лишь пометит память как read-only. volatile скажет "всегда читать значение из памяти". В итоге получится бессмысленная конструкция "всегда читать из памяти данные, данные изменять запрещено". Такой себе писсимизатор (как антоним оптимизатору).

Добавлено через 4 минуты
упс, некропост.
0
Kastaneda
Jesus loves me
Эксперт С++
4950 / 3027 / 347
Регистрация: 12.12.2009
Сообщений: 7,630
Записей в блоге: 2
Завершенные тесты: 1
07.10.2012, 09:50 20
Цитата Сообщение от 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
07.10.2012, 09:50
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.10.2012, 09:50

Квалификатор const
Квалификатор const часто используется для того, чтобы предотвратить изменение...

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

В чем отличие const и define ?
В чем-же?


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru