The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Выпуск языка программирования Rust 1.77"
Версия для распечатки Пред. тема | След. тема
Форум Разговоры, обсуждение новостей
Исходное сообщение [ Отслеживать ]

. "Выпуск языка программирования Rust 1.77" +/
Сообщение от n00by (ok), 26-Мрт-24, 20:20 
>> Если речь именно о плюсах, а не Си, то нет существенной в данном контексте (особенно, когда нет static и область видимости не очевидна) разницы. И то и то не занимает места в секции данных, будет подставлено непосредственным операндом в машинную инструкцию.
> Не совсем. const int my_constant может быть операндом операции взятия адреса, и
> все такие операции должны возвращать одинаковый адрес.

Я не просто так пишу про static. Наверное, ещё и область видимости стоило бы добавить. Если вернуть адрес автоматической переменной из функции, это UB, но как бы можно, да.

Исходный вопрос, как я понял, сугубо практический. Вроде "я так всегда делал, адрес не брал, и оно в коде ведёт себя как enum".

> В случае же с
> enum { my_constant = 5}, каждое взятие адреса &my_constant может возвращать
> свой собственный адрес. Технически правда, я думаю они всё равно все
> будут одинаковыми, но это не гарантия компилятора, это способ имплементации компилятора.

Вы изначально всё верно писали, но тут принялись мне объяснять лишнее и не туда зашли. Это не lvalue. Если передать my_constant параметром в функцию, то адрес у аргумента получить можно, но это окажется неявно созданная копия.

>> Это в случае переменных со связыванием. Отсюда при отсутствии static и возникает вопрос, а не определяется ли константа вот так
> Тут компилятор тоже должен предоставить константе валидный адрес, другое дело, что если
> оптимизатор достаточно умён, и видя что время жизни ограничено лексическим скоупом,
> он может подметить ситуацию, когда адрес не используется. Такие штуки становятся
> сложнее, если константная переменная доступна для юнита (топ-левел декларация static const
> int), потому что то в чём компиль реально силён, и ещё
> сложнее, если она не ограничена юнитом (там только LTO может помочь,
> теоретически, а практически я не знаю, помогает ли он).

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

>> В Си ничего нет про аллокацию на стеке. Там это называется automatic storage duration, и всякий сишник знает, что стека может вообще не быть.
> Сишное мышление проявляется не в использовании слова "стек", а в озабоченности стораджем
> в ущерб всему остальному. C не проводит чётко разницы между, например,
> переменной, сторейжем ассоциированным с ней, и значением сохранённым в этом сторейже.

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

> Лол, из-за этого, я когда столкнулся с растом впервые, недели две
> бился головой о клавиатуру, не мог понять логики. Сторейж переменной может
> меняться по ходу дела, компилятор не даёт гарантий на этот счёт,
> значение в строейже может меняться, или сторейж может уходить от одной
> переменной к другой (например когда ты делаешь move: let my_big_value =
> ...; foo(my_big_value); функция foo будет работать с тем же самым куском
> сторейжа, который был ассоциирован с my_big_value, но переменная в ней будет
> другая).

Логика Rust довольно простая. Автор посмотрел на OCaml и его осенила гениальная мысль - почему бы в Си++ не сделать всё const по умолчанию, ведь это разом решит множество проблем (в частности избавит от всяких фокусов вроде возврата ссылки на локальную статическую переменную, что бы скрыть связывание). Но позже почему-то ушёл из проекта.

>[оверквотинг удален]
> my_big_value отправляем в функцию, она может начать менять это значение. А
> вот константа... ты не можешь у неё отнять сторейж, ты не
> можешь изменить значение хранящееся в нём. Ты не можешь "затенить" константу
> другой декларацией, чтобы создать лексическую изменяемость:
> const int x = 5;
> {
>     const int x = 6;
>     cout << "лол я изменил значение константы x: " << x << endl;
> }
> cout << "фак ю, она осталась прежней: " << x << endl;

#include <iostream>

const struct { mutable int x; } X = { 5 };

int main() {
  X.x = 6;
  std::cout << "я действительно изменил значение константы X: " << X.x << std::endl;
}
// не та область видимости
// std::cout << "лол я изменил значение константы x: " << x << std::endl;

Оно в принципе будет работать и с extern const int x, если определить ссылку на константу через const_cast, но придётся менять защиту страницы памяти константной секции ELF-а, что бы не упало при попытке записи. Что бы не заморачиваться, приходится прибегать к фокусам:

struct { const int x; int y; } X = { 5 };

int main() {
  int& xx = const_cast<int&>(X.x);
  xx = 6;
  std::cout << "я действительно изменил значение константы x: " << X.x << std::endl;
}

> Вот в расте такое не прокатит. С let декларацией ты можешь так
> поступать, создавая новый бинд взамен старого, с const'ом так уже не
> выйдет.

Так в том примере две разные переменные с одним именем.

>> Ну как кто? Вон выше было "первое же -- это имя, с которым линкеру придётся разбираться".
> В примере имя lexically scoped в функции. Оно не появляется в таблице
> имён линкера, все такие имена разрешаются компилятором.

Значит нет неявного static, то есть переменная не имеет связывания, не хранится в секции данных. Пока кто-то не пытается взять её адрес, она крякает как enum.

Ответить | Правка | Наверх | Cообщить модератору

Оглавление
Выпуск языка программирования Rust 1.77, opennews, 22-Мрт-24, 14:05  [смотреть все]
Форумы | Темы | Пред. тема | След. тема



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру