Перейти к содержанию
    

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

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";
      |                ^~~~~~~~~~~
$

 

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, one_eight_seven сказал:

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, jcxz said:

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

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

2 minutes ago, jcxz said:

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

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

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Darth Vader said:

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, Darth Vader said:

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 часов назад, esaulenka сказал:

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 hours ago, Darth Vader said:

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

28.09.2020 в 12:34, one_eight_seven сказал:

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...