Jump to content

    
inventor

модификатор const. Как правильно использовать в Си

Recommended Posts

P.S. Подумал ещё, и стал ещё сильнее согласен с тем, что на этапе компиляции такое проверять правильно.
Добавил:
 

-Wwrite-strings

И получил:
 

$ gcc -Wall -Wextra -pedantic -Wwrite-strings tst.c
tst.c: In function main’:
tst.c:9:16: warning: initialization discards const qualifier from pointer target type [-Wdiscarded-qualifiers]
    9 |     char * p = "inmutable";
      |                ^~~~~~~~~~~
$

 

Edited by one_eight_seven

Share this post


Link to post
Share on other sites
16 минут назад, one_eight_seven сказал:

Не согласен. Это не работа компилятора. Это работа статического анализатора кода, lint или чего-то в этом роде.

В первом случае указатель прямо указывает на string literal.

Указателю присваивается адрес строки в RO-секции.

На попытку присваивания не const-указателю адреса const-объекта, компилятор такой warning/error выдаёт. А здесь операция аналогичная, а значит и реакция должна быть аналогичной.

Share this post


Link to post
Share on other sites
1 minute ago, jcxz said:

Указателю присваивается адрес строки в RO-секции.

Да-да. Одним постом выше я об этом написал. Да и в том посте было согласие с тем, что ключи компиляции для этого должны быть.

2 minutes ago, jcxz said:

На попытку присваивания не const-указателю адреса const-объекта, компилятор такой warning/error выдаёт.

Да, это ещё одна проблема языка C. В нём разные действия выглядят одинаково. Использование указателей разительно отличается от их объявления. А выглядит очень похоже.

Edited by one_eight_seven

Share this post


Link to post
Share on other sites
1 час назад, jcxz сказал:
2 часа назад, one_eight_seven сказал:

Например, вот это вызовет Segfault:



char * p = "inmutable";
p[1] = 'm';

 

Вот это-то и плохо. По уму тут компилятор должен выдать warning/error. На первую строчку.

Он бы и рад, но стандарт (включая редакцию от 2011года) гласит:

Цитата

6.7.8 Initialization

....

EXAMPLE 8 The declaration
char s[] = "abc", t[3] = "abc";
defines ‘‘plain’’ char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type ‘‘pointer to char’’ and initializes it to point to an object with type ‘‘array of char’’
with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to
modify the contents of the array, the behavior is undefined.

 

Share this post


Link to post
Share on other sites

Кто объяснит, почему статический метод класса одновременно не может быть константным? В моем понимании, это независимые и не противаречащие друг другу вещи. Как теплое и мягкое. Они сообщают компилятору и программисту разную информацию, говорят о разных вещах. Но применять их вместе почему-то нельзя...

// Объявление метода в классе:

static void foo() const; // компилятор выдает ошибку на const

Share this post


Link to post
Share on other sites
1 hour ago, Darth Vader said:

почему статический метод класса одновременно не может быть константным? В моем понимании

А какое у Вас понимание?

В данном случае, const - это метод, который не меняет экземпляр класса (т.е. только читает его переменные), static - метод, который вообще не требует наличия экземпляра (т.е. в принципе не может ничего поменять). Следовательно, static метод по определению const.

Share this post


Link to post
Share on other sites
3 hours ago, Darth Vader said:

Кто объяснит, почему статический метод класса одновременно не может быть константным?

Присоединяюсь к @esaulenka, а какое у вас понимание?

Насколько я могу объяснить, модификатор const, применительно к методу класса, влияет не на метод класса, а на указатель this. Т.е. если у нас class C, то this в данном случае будет типа C const *, в то время как для неконстантного метода он будет C *.

А статические методы не имеют указателя this в принципе.

Share this post


Link to post
Share on other sites
9 часов назад, esaulenka сказал:

В данном случае, const - это метод, который не меняет экземпляр класса (т.е. только читает его переменные), static - метод, который вообще не требует наличия экземпляра (т.е. в принципе не может ничего поменять).

Такое же, но с одним нюансом.

const-метод не должен менять никаких данных класса, в том числе и статических. Да, они (статические данные класса) не принадлежат конкретному объекту (экземпляру) класса, они общие для них всех. Но это не исключает их из данных класса. Поэтому статический метод, изменяющий статические данные класса, не может считаться константным методом.

Я так понимаю.

Share this post


Link to post
Share on other sites
5 hours ago, Darth Vader said:

Такое же, но с одним нюансом.

const-метод не должен менять никаких данных класса, в том числе и статических. Да, они (статические данные класса) не принадлежат конкретному объекту (экземпляру) класса, они общие для них всех. Но это не исключает их из данных класса. Поэтому статический метод, изменяющий статические данные класса, не может считаться константным методом.

Я так понимаю.

Нет. const-метод вполне может изменять следующие типы данных:

  1. mutable поля класса
  2. любые данные, к которым класс имеет неконстнантный доступ. т.е. которые для класса не являются константой:
  • те, к которым он имеет доступ по указателям и ссылкам (технически, метод не меняет поле класса, оно остаётся неизменным, но данные, доступные по этим полям - изменяемы)
  • данные, передаваемые в const-метод по указателю или ссылке в качестве аргументов
  • через указатели или ссылки, возвращаемые функциями
  • напрямую доступные через namespace или класс - такие, как статические члены.

Share this post


Link to post
Share on other sites
28.09.2020 в 12:34, one_eight_seven сказал:

модификатор const, применительно к методу класса, влияет не на метод класса, а на указатель this. Т.е. если у нас class C, то this в данном случае будет типа C const *, в то время как для неконстантного метода он будет C *.

Хорошее объяснение.

18 часов назад, one_eight_seven сказал:

const-метод вполне может изменять следующие типы данных:

Понятно. Спасибо.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.