Const char c что это
Перейти к содержимому

Const char c что это

  • автор:

Const char c что это

В действительности, в соответствии со стандартом на языки C и C++ (правило чтения операторов «Read Declarations Right-to-Left«, т. е. надо читать всегда оператор справа налево), модификатор const влияет на элемент, слева от которого стоит const. Поэтому если использовать const перед типом, то это фактически ничего не значит, и используется просто для удобства запоминания.

К примеру, следующие два оператора совершенно эквивалентны:

char const * УказательНаНЕизменяемоеСодержимое1;
const char * УказательНаНЕизменяемоеСодержимое2;

Оба указателя УказательНаНеизменяемоеСодержимое1 и УказательНаНеизменяемоеСодержимое2 указывают на строку, являющуюся константой, и оба эти указателя можно модифицировать runtime в коде программы.

Примечание: в какой реально памяти находится константа — зависит от платформы, для которой компилируется код. Например, для процессоров ARM встраиваемых систем константа может находиться в памяти программ FLASH, а для процессоров PC константы, как и обычные переменные, хранятся в памяти RAM.

Если же Вы хотели получить от указателя другое, чтобы это был постоянный указатель, который нельзя модифицировать, то нужно поместить const после звездочки (тогда получится наоборот, строка может быть изменяемой, а сам указатель изменить нельзя):

char * const НЕизменяемыйУказательНаИзменяемоеСодержимое;

Чтобы защитить от изменения как сам указатель, так и содержимое, на которое он указывает, то нужно использовать два ключевых слова const:

char const * const НЕизменяемыйУказательНаНЕизменяемоеСодержимое;

[Примеры ключевого слова const при использовании с указателями]

Ключевое слово const используется, когда мы хотим сделать что-то — наподобие переменной — доступным только для чтения. При этом это что-то совсем не обязательно может храниться в памяти ROM, данные объекта «только для чтения» могут храниться и в RAM (зависит от используемой платформы, для которой компилируется код). Ниже приведено несколько примеров использования ключевого слова const.

const int j = 10;

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

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

Указатель на константу указывает на данные, которые должны быть постоянными. Это просто означает, что мы не можем поменять данные, на которые ссылается указатель. Вот несколько примеров кода, иллюстрирущие то, что мы подразумеваем указателем на константу:

// Создание указателя на константу:
const char* pntr = "не изменяемые данные";
// Это тоже создает указатель на константу. Хотя здесь синтаксис
// отличается от приведенного выше, это в сущности одно и то же.
char const* pntr = "не изменяемые данные";
// Этот код приведет к ошибке, потому что данные не могут быть
// изменены.
*pntr = "проверка";
// Но этот код считается безошибочным, потому что адрес указателя
// можно поменять (сам указатель не константа). pntr = "проверка";

Постоянный указатель. В таком указателе находящийся в нем адрес является константой. Но сама переменная, на которую ссылается указатель может быть изменена, т. е. она может не являться константой. Вот несколько примеров:

// Это определение const-указателя, хранящийся в нем
// адрес поменять нельзя, но сами данные поменять можно.
char* const pntr = "какие-то данные";
// Этот код корректен и допустим, потому что данные менять можно:
*pntr = "проверка";
// Но этот код приведет к ошибке, потому что адрес
// постоянного указателя поменять нельзя: pntr = "проверка";

Постоянный указатель на константу. Можно думать об этом случае как о комбинации двух примеров выше. Т. е. нельзя поменять ни сам адрес (значение указателя), ни данные, на которые он указывает. Пример:

// Это const-указатель на константу.
const char* const pntr = "Это поменять нельзя";

[Ссылки]

1. const char* and char const* — are they the same? site:stackoverflow.com .
2. Барт Симпсон Генератор картинок онлайн site:advice-dog.ru .
3. Использование описателя const в C.
4. Как читать сложные декларации C/C++.

Комментарии

+4 #1 Ruslan 22.04.2020 19:03

Но позвольте, вы же говорите что const влияет только на содержимое слева от const, а сами используете const самым левым (т.е. не влияющим ни на что).

/*const int j = 10;
В этом простом примере если мы попробуем в коде присвоить значение переменной j, то это будет обнаружено на этапе компиляции программы, компилятор выдаст ошибку.» */

Чем отличается const char* от char*?

Доброго всем дня!
Из матчасти я понимаю, что char* — это указатель массив символов, тогда как const char* — это константный указатель на массив символов.

Но вот чего не понимаю

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include #include #include using namespace std; int main() { char* a = "mur "; const char * b = "2"; char* arr = strcat(a,b); cout  arr  endl; return 0; }

Почему на strcat выпадает ошибка? Хотя входящие типы данных полностью соответствуют сигнатуре..

У меня получилось запустить эту функцию в таком виде:

1 2 3 4 5 6 7
int c=5; char ar[2]; itoa(c,ar,10); char* arr = strcat(ar,"2333"); cout  arr  endl;

И даже в таком виде:

1 2 3
char* b = "2333"; char* arr = strcat(ar,b); cout  arr  endl;

где b — даже неконстантный указатель, то есть не соответствует сигнатуре, но заработало. В чем разница между

char ar[2];
char* a = "mur ";

Это ж по идее один и тот же тип данных?
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:

Чем отличаются объявления const char* и const* char
Прошу объяснить мне, чем отличаются объявления const char* и const* char и как объявить: указатель.

Строка: чем отличается строки string, char, char*?
Помогите разобраться,совсем плохо идёт,чем отличается строки string,char,char* И если можно пару.

Error C2664: sprintf: невозможно преобразовать параметр 1 из ‘const char *’ в ‘char *’
error C2664: sprintf: невозможно преобразовать параметр 1 из ‘const char *’ в ‘char *’ void.

1582 / 1216 / 345
Регистрация: 14.05.2017
Сообщений: 3,939

ЦитатаСообщение от netBool Посмотреть сообщение

char* — это указатель массив символов, тогда как const char* — это константный указатель на массив символов

Нет. char* — указатель на символ. То есть для того, чтоб char* а стал указателем на первый символ из массива, нужно сделать так:

char ar[2]; char* a = ar;

Добавлено через 7 минут
А строковые литералы наподобие «mur » — это константы, точно такие же как например числа. Ты же в своём коде не пытаешься присваивать

6 = 2; 2*2 = 5;

The behavior is undefined if the destination array is not large enough for the contents of both src and dest and the terminating null character.

то есть ты обязан создать массив, в который всё гарантированно поместится, и только после этого применять данную функцию. То есть

1 2 3 4 5 6 7 8 9
int main() { char a[6] = "mur "; const char * b = "2"; char* arr = strcat(a,b); // 4 символа исходной строки + 1 добавленный символ + символ конца строки = нужно 6 символов cout  arr  endl; return 0; }

Добавлено через 4 минуты
По поводу всего этого можешь прочитать подробнее тут — https://www.cyberforum.ru/blogs/18334/blog97.html

А вообще гораздо проще будет работать с std::string . Всё-таки вышеописанные строки и функция strcat — наследие С.

325 / 304 / 173
Регистрация: 16.11.2010
Сообщений: 1,069
Записей в блоге: 9

ЦитатаСообщение от TRam_ Посмотреть сообщение

Вот этот момент, мне пожалуй, и не понятен

char* a = "mur ";

ведь по сути это это тоже массив. А char* — указатель на 1й элемент массива.
Короче, если мои мысли текут в верном направлении, то «mur » будет храниться как константа в секции .text, куда запись запрещена, поэтому и ошибка.

ЦитатаСообщение от TRam_ Посмотреть сообщение

то есть ты обязан создать массив, в который всё гарантированно поместится, и только после этого применять данную функцию. То есть

Понял, спасибо
2341 / 805 / 305
Регистрация: 10.02.2018
Сообщений: 1,891
b — даже неконстантный указатель, то есть не соответствует сигнатуре

Вот тут как раз всё в порядке. Указатель автоматически преобразуется к нужному типу. Если это невозможно, то выдаётся сообщение об ошибке компиляции. Константный модификатор в аргументах подчёркивает, что запись по этому указателю в процессе работы функции не планируется, только чтение. Передавать в таком аргументе можно как обычный указатель, так и константный, в отличие от ситуации, когда аргумент объявлен не как константный.

ЦитатаСообщение от netBool Посмотреть сообщение

«mur » будет храниться как константа в секции .text, куда запись запрещена, поэтому и ошибка

Да, при компиляции под виндой так и получается. Фактически, тип указанный компилятору не соответствует содержимому. Протектор памяти не позволяет запись, хоть тип объявлен как char* . Для кода

char[] = "mur "

происходит выделение памяти в допустимом для записи месте и копирование туда строки из константной секции.

В чем смысл типа char * const* в языке Си?

char* — указатель на переменную типа char. char* const — константный указатель. const char* — указатель на константную переменную. const char* const — константный указатель на константу. char const* — тоже самое, что и const char* . Автоматически в него преобразуется. Но про char* const* компилятор gcc(c99) рассуждает, как об отдельном типе. Тоже самое с const char* const* . В чем заключается смысл * после const вкупе с char* ? Как описать этот тип?

Отслеживать
kalokusatel
задан 14 сен 2016 в 14:39
kalokusatel kalokusatel
391 1 1 золотой знак 5 5 серебряных знаков 7 7 бронзовых знаков
char* const* без const будет char** т.е. это массив на константные строки.
14 сен 2016 в 14:41
Такие объявления проще читаются справа налево.
14 сен 2016 в 14:41

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

Это такой же указатель на указатель, как char** , только менять его адрес (того указателя, на который указывает переменная) нельзя.

 char* pc1 = (char*)malloc(LENGTH); strcpy(pc1, "Hello"); char* pc2 = (char*)malloc(LENGTH); strcpy(pc2, "World"); char* const* ppc1 = &pc1; // OK *ppc1 = pc2; // compile-time error char** ppc2 = &pc1; // OK *ppc2 = pc2; // OK 

Отслеживать
ответ дан 14 сен 2016 в 14:42
8,656 1 1 золотой знак 16 16 серебряных знаков 32 32 бронзовых знака

Расшифровывать подобные обозначения (и более суровые, с участием указателей на функции, например) порой сильно помогает ресурс cdecl

char* const* x 

declare x as pointer to const pointer to char

x это указатель на константный указатель на char

— ссылка

x ( char* const* ) менять можно.
*x ( char* const ) менять нельзя.
**x ( char ) менять можно.

Отслеживать
ответ дан 14 сен 2016 в 14:48
user181100 user181100

Цитата из книги Бена Клеменса «Язык С в XXI веке» (Глава 8, Ключевое слово const):

Объявления следует читать справа налево. Таким образом:

  • int const — константное целое;
  • int const * — (неконстантный) указатель на константное целое;
  • int * const — константный указатель на (неконстантное) целое;
  • int * const * — указатель на константный указатель на целое;
  • int const * * — указатель на указатель на константное целое;
  • int const * const * — указатель на константный указатель на константное целое.

Как видите, квалификатор const всегда относится к тому, что находится слева от него, — как и * .

Можно переставить местами имя типа и const , то есть int const и const int — одно и то же (хотя проделать этот фокус с const и * не удастся). Я предпочитаю форму int const , потому что она согласуется с более сложными конструкциями и прави­лом чтения справа налево. Но чаще встречается форма const int , быть может, по­тому что её проще произнести на обычном языке (константное целое) или потому что так «всегда делали». Так или иначе, годятся оба варианта.

В статье на хабре Так вы думаете, что знаете Const? пошли ещё дальше и добавили третий квалификатор const :

  • int const * const * const — константный указатель на константный указатель на константное целое.

Const char c что это

Стандартная библиотека языка С++ предоставляет программистам строковый тип данных (избавляет от использования массивов символов char[ ]).

Мы будем использовать тип данных string наряду со стандартными встроенными типами данных. И вы на первый взгляд не будете замечать никаких различий, хотя на самом деле это абстрактный тип данных, созданный на основе объектно-ориентированных возможностей языка С++. Надеюсь со временем вы тоже сможете создавать АТД, которыми можно будет пользоваться так же удобно и свободно, как и классом string.

Строковый тип данных позволяет хранить строки переменной длины, причем длину можно менять в процессе выполнения программы. Строковый тип представляет операторы, выполняющие такие операции над строками, как контеканация, присваивание, замещение и др.

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

void main()
string name=»Vitaly»; // объявление, определение, инициализация
string lastname=»Domnenko»;

name+=»M.»+lastname; // конкатенация с присваиванием (накапливающее присваивание)
cout >

Используя [ ] можно получить символ из любой позиции

char ch=name[5]; // символы нумеруются с нуля

Лексикографическое сравнение осуществляется с использованием операторов == < >= !=. При лексикографическом сравнении последовательно сравниваются коды символов строки. Те символы считаются «больше», чьи коды «больше»и наоборот.

Кодировка (кодовая таблица) — это однозначное соответствие между целым число (кодом) и символом. При этом символ — это буква, цифра и другие графические знаки. Кодировки обычно составляют так, что символы следуют в алфавитном порядке и символ ‘а’ имеет наименьший код, а символ ‘z’ наибольший. Таким образом, выполняя лексикографическое сравнение можно разместить слова (строки) в алфавитном порядке. Это справедливо и для символов кириллического алфавита. Но не всегда, т.к. существует кодировки, в которой кириллические символы располагаются не в алфавитном порядке. Это кодировка КОИ8, которая обычно используется в операционных системах UNIX. Если вы пишете программу для UNIX, то нужно помнить, что простое лексикографическое сравнение не даст ожидаемого результата и нужно усложнять программу.

В нашем случае (при программировании для DOS или Windows) используются кодировки CP866 и СP1251 лексикографическое сравнение справедливо и дает нужный результат.

Ну и операторы для ввода/вывода строковых переменных >>

Функция Описание
Конструкторы
string() конструктор по умолчанию, создает пустую строку
string(const char* p) преобразующий конструктор
string(const string& str, size t pos=0, size t n=npos) копирующий конструктор (npos обычно равен -1 и указывает, что память не была выделена)
string(const char* p, size_t n) копирует n символов, р является базовым адресом
string(char c, size t n=l) создает строку из n символов с
Перегруженные операторы
string& operator= (const string& s) оператор присваивания
string& operator+= (const string& s) добавляет строку
char operator[] (size t pos) const возвращает символ из позиции pos
char& operator[] (size t pos) возвращает ссылку на символ из позиции pos
Функции-члены
string& append(const string& s, size_t pos=0, size t n=npos); Добавляет n символов начиная от позиции pos
string& assign(const string& s, size_t pos=0, size_t n=npos); строковому объекту присваивается n символов, начиная от позиции pos
string& insert(size_t posl, const string& str, size_t pos2=0 , size_t n=npos); вставляет n символов, полученных из str, начиная с позиции pos2, в строку с позиции posl
string& remove(size_t pos=0 , size_t n=npos); Удаляются n символов из строки начиная с позиции pos
string& replace(posl, nl, str, pos2=0, n2=npos); в неявной строке начиная с позиции posl заменяет nl символов n2 символами из подстроки str с позиции pos2
string& replace(pos, n, p, n2); заменяет n символов в позиции pos используя char* p из n2 символов или char* p до завершающего нуля, или повторяя символ с rep раз
char get_at (pos) const; возвращает символ из позиции pos
void put_at (pos, c); помещает символ с в позицию pos
size_t length() const; возвращает длину строки
const char* c_str() const; преобразует строку в традиционное char* представление
const char* data() const; возвращает базовый адрес строкового представления
void resize(n, c); void resize(n); изменяет строку, делая ее длину равной п; в первой функции в качестве заполняющего символа выступает с, а во второй — символ eos () (end-of-string, конец строки)
void reserve(size_t res_arg);size_t reserve() const; выделяет память под строку; первая функция переустанавливает this; вторая возвращает закрытый член res — размер выделенного фрагмента
size_t copy(p, n, pos=0) const; п симолов строки, начиная с позиции pos, копируются в char* p
string substr(pos=0, n=pos) const; возвращается подстрока из п символов строки
int compare(const string& str, size_t pos=0, size_t n=npos) const; сравнивает п символов строки, начиная с позиции pos, со строкой str. Возвращается ноль, если строки равны; в противном случае возвращается положительное или отрицательное целое значение, показывающее, что неявная строка лексикографически больше или меньше чем строка str.
size_t find (const string& str, size_t pos=0) const; в строке начиная с позиции pos производится поиск строки str. Если она найдена, возвращается позиция, в которой она начинается; в противном случае возвращается позиция npos
size_t rfind(str, pos=npos) const; похоже на find (), но при поиске первого совпадения строка сканируется в обратном направлении
size_t find_first_of(str, pos=0) const; производится поиск первого вхождения str начиная с позиции pos
size_t find_last_of(str, pos=npos) const; аналогично, но в обратном направлении
size_t find_first_not_of(str, pos=0) const; производится поиск первого символа, который не соответствует ни одному из символов str начиная с позиции pos
size_t find_last_not_of(str, pos=npos) const; аналогично, но в обратном направлении
Пример работы со строками
///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 2.1. Пример работы со сроками // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include // подключение библиотеки ввода-вывода #include // подключение библиотеки ввода-вывода в файл #include // подключение описания string using namespace std; // подключение стандартного пространства имен для использования библиотек ///////////////////////////////////////////////////////////////////////////// void main() < ifstream ifile("test.html"); // создание потока ввода из файла по его имени string data; // строка куда будут записаны данные // цикл будет выполняться до тех пор, пока не встретиться конец файла while(!ifile.eof()) < string sLine; getline(ifile, sLine, '\n'); // читаем строку из файла до символа конца строки data+=sLine; // записываем прочитанную строку в конец итоговой > size_t num_first=0; // номер символа, с которого будет происходить поиск // бесконечный цикл, выход из цикла - по оператору break while(true) < // находим номер символа, с которого начинается подстрока " // если такого текста не нашли - выход из цикла num_first=data.find(", num_first); if(num_first==string::npos) break; // находим номер символа, с которого начинается подстрока ">", начиная с символа под номером num_first+1 // если такого текста не нашли - выход из цикла size_t num_last=data.find(">", num_first+1); if(num_last==string::npos) break; // выделяем подстроку от "" string image_data=data.substr(num_first+1, num_last-num_first-1); // запоминаем символ, начиная с которого будем искать в следующий раз num_first=num_last+1; // ищем номер символа, с которого начинается подстрока "src="" // (для задания подстроки используем экранирующий символ) size_t num_first2=image_data.find("src=\""); // если такая подстрока была найдена if(num_first2!=string::npos) < // ищем закрывающую кавычку size_t num_last2=image_data.find("\"", num_first2+6); // если такая подстрока была найдена - выделяем в отдельную строку имя файла и выводим на экран if(num_last2!=string::npos) < string image_name=image_data.substr(num_first2+5, num_last2-num_first2-5); cout> >; > ///////////////////////////////////////////////////////////////////////////// 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *