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

Что то не пойму данный вариант. Структура получает указатель на начало строки  и сохраняет в указателе   temp

передает указатель  в структуру  так по кругу

Где физически храняться эти строки в памяти ? в Куче?  когда эта память освобождаеться? Когда я грохну конкретную структуру?

void main(){

char* temp ;
    
strTT *strart = (strTT*)malloc(sizeof(strTT));

strTT myStr;

temp ="asd11111";
strart->Mystr = temp;
temp ="qwe222222";
(strart+1)->Mystr = temp;

    printf("%s\n",  strart->Mystr );
    printf("%s\n",  (strart+1)->Mystr );

}

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


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

46 минут назад, spirit_1 сказал:

Что то не пойму данный вариант. Структура получает указатель на начало строки  и сохраняет в указателе   temp

передает указатель  в структуру  так по кругу

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

46 минут назад, spirit_1 сказал:

Где физически храняться эти строки в памяти ? в Куче?

В статической памяти.

46 минут назад, spirit_1 сказал:

  когда эта память освобождаеться?

Когда программа завершится.

46 минут назад, spirit_1 сказал:

char* temp ;

temp ="asd11111";

Безграмотная запись. Потенциальный выстрел себе в ногу. Писать следует: char const *temp; temp = "asd11111"

46 минут назад, spirit_1 сказал:

strart->Mystr = temp;

Вы очевидно предлагаете угадывать - что такое Mystr?

46 минут назад, spirit_1 сказал:

(strart+1)->Mystr = temp;

Здесь очевидно вы решили завесить программу или вылететь в исключение?

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


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

36 minutes ago, spirit_1 said:

char* temp ;

Создали указатель на стеке, пока что указывает "в никуда".

36 minutes ago, spirit_1 said:

strTT *strart = (strTT*)malloc(sizeof(strTT));

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

37 minutes ago, spirit_1 said:

strTT myStr;

Создали структуру на стеке. Они нигде не используется, эту строчку можно удалить.

37 minutes ago, spirit_1 said:

temp ="asd11111";

Литерал в статической памяти (создаётся при старте программы), указатель теперь указывает на него

37 minutes ago, spirit_1 said:

strart->Mystr = temp;

Поле структуры (сама структура в куче), являющееся указателем, указывает на литерал в статической памяти.

39 minutes ago, spirit_1 said:

temp ="qwe222222";

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

39 minutes ago, spirit_1 said:

(strart+1)->Mystr = temp;

Поле структуры (сама структура в куче), являющееся указателем, указывает на литерал в статической памяти. Кстати, (strart+1) на самом деле не существует, под него никто память не выделил - malloc был только на один элемент, не на два. Это ошибка.

40 minutes ago, spirit_1 said:

printf("%s\n",  strart->Mystr );

Выведет первый литерал - "asd11111".

41 minutes ago, spirit_1 said:

printf("%s\n",  (strart+1)->Mystr );

Выведет второй литерал - "qwe222222". Не считая ошибки с невыделенной памятью под эту структуру.

 

По вашим вопросам.

43 minutes ago, spirit_1 said:

Где физически храняться эти строки в памяти ?

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

44 minutes ago, spirit_1 said:

когда эта память освобождаеться?

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

45 minutes ago, spirit_1 said:

Когда я грохну конкретную структуру?

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

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


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

2 минуты назад, engel65536 сказал:

Создали указатель на стеке, пока что указывает "в никуда".

Не "на стеке", а "в автоматической памяти". Это может быть как стек так и регистр.

2 минуты назад, engel65536 сказал:

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

...которая освободится при завершении программы. А значит и память занимаемая этими строками - тоже.

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


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

On 11/11/2023 at 12:32 PM, jcxz said:

Не "на стеке", а "в автоматической памяти". Это может быть как стек так и регистр.

...которая освободится при завершении программы. А значит и память занимаемая этими строками - тоже.

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

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


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

On 11/11/2023 at 12:27 PM, engel65536 said:

Создали указатель на стеке, пока что указывает "в никуда".

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

Создали структуру на стеке. Они нигде не используется, эту строчку можно удалить.

Литерал в статической памяти (создаётся при старте программы), указатель теперь указывает на него

Поле структуры (сама структура в куче), являющееся указателем, указывает на литерал в статической памяти.

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

Поле структуры (сама структура в куче), являющееся указателем, указывает на литерал в статической памяти. Кстати, (strart+1) на самом деле не существует, под него никто память не выделил - malloc был только на один элемент, не на два. Это ошибка.

Выведет первый литерал - "asd11111".

Выведет второй литерал - "qwe222222". Не считая ошибки с невыделенной памятью под эту структуру.

 

По вашим вопросам.

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

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

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

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

и записали тутда temp   и завершили фунцию. temp  как локальная переменная исчезла после завершения функции

typedef struct{
int a;
char *Mystr;

}strTT;

 

..--------------------------------

 

void yy(strTT *strIn){


   char* temp ="asd11111";
   strIn->Mystr = temp;

    }
..--------------------------------------

далее в мэйн

strTT *strart = (strTT*)malloc(sizeof(strTT));

yy(strart);

printf("%s\n",  strart->Mystr );

 

 

как в данном случае??  сколько программа будет держать в памяти эту строку?  "asd11111";

Я позреваю что в данном случае мне принт вывел  asd11111 просто потому что программа еще не успела занять эту ячейку другими переменными

Поскольку она была локальна и для программы уже погибла после завершения функции и теперь м эйне мы выели просто мусор по этому адресу 

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


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

On 11/11/2023 at 2:12 PM, aaarrr said:

Не путайте указатель и объект.

я понимаю разницу поэтому и спрашиваю .  

в данном случае 

char* temp ="asd11111";

создали указатель  temp

 затем  гдето в памяти по адресу ХХХХ содали физически строку  строку "asd11111"

далее дали нашему указателю адрес этой строки

функция вернула указатель на этот адрес

Но функция после этого завершилась и этот обьект как бы исчез.  Программа считает этот участок памяти свободным

по факту?  Т.е указатель по факту указывает на обьтект(строку) которой уже нет для программы

Верно?

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


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

Регулярно появляются человеки, споткнувшиеся на теме указателей 🙂 

Указатель - это переменная с некоторым адресом, хранящая в себе число, являющееся адресом другой переменной, на которую указывает указатель. Строка - это массив однобайтных переменных или констант. Стока может быть определена в виде массива или в виде указателя на массив. Обратите внимание на положение массива в адресном пространистве. Когда строка определена как указатель, то он указывает на местоположение константных данных. Как правило, это флеш-память. (я запустил из ОЗУ, поэтому адрес массива в этом случае находится тоже в ОЗУ, но в области текста программы).

2023-11-11194757.thumb.jpg.de9212493c1c54779079b354aaa1fe80.jpg

Что касается динамического выделения памяти, то это уже другая категория. Положение кучи в ОЗУ задается пользователем или выбирается компилятором автоматически. Соответственно, указатель, присвоенный через malloc() будет указывать на область кучи. И если вы удалите (освободите) память по этому указателю через free(), то данные, располагаемые по этому адресу, могут стать недействительными (перезаписанными другими процессами).

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

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


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

On 11/11/2023 at 2:44 PM, EdgeAligned said:

Регулярно появляются человеки, споткнувшиеся на теме указателей 🙂 

Указатель - это переменная с некоторым адресом, хранящая в себе число, являющееся адресом другой переменной, на которую указывает указатель. Строка - это массив однобайтных переменных или констант. Стока может быть определена в виде массива или в виде указателя на массив. Обратите внимание на положение массива в адресном пространистве. Когда строка определена как указатель, то он указывает на местоположение константных данных. Как правило, это флеш-память. (я запустил из ОЗУ, поэтому адрес массива в этом случае находится тоже в ОЗУ, но в области текста программы).

2023-11-11194757.thumb.jpg.de9212493c1c54779079b354aaa1fe80.jpg

Что касается динамического выделения памяти, то это уже другая категория. Положение кучи в ОЗУ задается пользователем или выбирается компилятором автоматически. Соответственно, указатель, присвоенный через malloc() будет указывать на область кучи. И если вы удалите (освободите) память по этому указателю через free(), то данные, располагаемые по этому адресу, могут стать недействительными (перезаписанными другими процессами).

 

"Строка - это массив однобайтных переменных или констант."

Все описанное выше понятно и не отвечает на вопрос , Приведу другой пример

В main имеем такое

 

char* temp ;

temp ="asd11111";

Время жизни этого участка памяти"asd11111"  ( не указателя  а именно содержимого строки в памяти) будет до окончания текущей функции , в данном случае мэйн?

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


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

Есть такое понятие, как локальные переменные функции и глобальные переменные.

Так вот, локальные нестатические переменные, объявленные внутри функции (main() - это тоже функция с временем жизни от входа в нее!), то переменные помещаются в стек вызовов и время их жизни будет от входа в функцию до выхода из нее. Для случая main() время жизни от входа в main и до завершения программы по любым причинам, например до выключения питания. Предполагаем, что в main() в конце есть бесконечный цикл while(1) { } без выхода из него.

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

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


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

47 минут назад, spirit_1 сказал:

я понимаю разницу поэтому и спрашиваю .  

Пишете "понимаете", и опять задаёте вопрос о том же самом.

Я же ещё в самом начале ответил:

2 часа назад, jcxz сказал:
3 часа назад, spirit_1 сказал:

Где физически храняться эти строки в памяти ? в Куче?

В статической памяти.

Т.е. - по факту ничего не поняли.

47 минут назад, spirit_1 сказал:

функция вернула указатель на этот адрес

Это где такое??? О чём вы?  :wacko2:

47 минут назад, spirit_1 сказал:

Но функция после этого завершилась и этот обьект как бы исчез.  Программа считает этот участок памяти свободным

Ещё раз:

2 часа назад, jcxz сказал:
3 часа назад, spirit_1 сказал:

  когда эта память освобождаеться?

Когда программа завершится.

Вы понимаете смысл ответов?

И опять - повторяете те же ошибки с присваиванием адресов const-объектов указателям на переменные.

Т.е. - толку ноль от всех ответов вам.

 

PS: Может всё-таки наконец-то открыть учебник по си и освоить хотя бы азы программирования на нём?

Узнать какие типы памяти бывают в си, что такое "указатели" и т.п.

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


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

Обратите внимание на расположение локальных, локальных статических и глобальных переменных и поведение стека вызовов и видимость переменных в зависимости от вызванных функций. Представлен хронологический порядок (слева направо, сверху вниз) - main(), вызов ф-ции Foo1(), вызов из нее Foo2(), возврат в Foo1(), возврат в main(). Когда функция вызывается, указатель вершины стека смещается вверх (в сторону меньших адресов) и образуется область для размещения локальных переменных функции. При выходе из функции указатель вершины стека смещается вниз (в сторону возрастания адресов), и оставшиеся за его пределами переменные хоть физически и не уничтожаются, но становятся недействительными и будут перезаписаны при следующем вызове других функций. Следовательно, указатели на локальные переменные функции будут являться неверными при выходе из этой функции. 
В функции main() переменные создаются при входе в нее и продолжают существовать до выключения питания (при условии работы бесконечного цикла while(1) без выхода).

 2023-11-11203741.thumb.jpg.f13fadbb65109e09b430f9a610ff8b5d.jpg  2023-11-11204347.thumb.jpg.ffae564b9b82b5d3739c568cb64eeb08.jpg

2023-11-11204432.thumb.jpg.9364d220bafaf0b0ec63bda675eb99c8.jpg  2023-11-11204458.thumb.jpg.eedc196ec4e12882ad13752fc252e6c7.jpg

2023-11-11204527.thumb.jpg.7e680d21cf4d9bfa32a53e79687b0c78.jpg

54 минуты назад, spirit_1 сказал:

не указателя  а именно содержимого строки в памяти

Содержимое в строке является константой, хранимой (чаще всего) в области флеша. Конкретно положение этих констант задает скрипт линкера, секция rodata . И как догадываетесь, то, что хранится во флеше, хранится вечно (по сравнению со временем жизни неконстантных переменных).

 

Изменено пользователем EdgeAligned
пронумеровал картинки, чтоб понятна была последовательность

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


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

On 11/11/2023 at 3:20 PM, jcxz said:

Пишете "понимаете", и опять задаёте вопрос о том же самом.

Я же ещё в самом начале ответил:

Т.е. - по факту ничего не поняли.

Это где такое??? О чём вы?  :wacko2:

Ещё раз:

Вы понимаете смысл ответов?

 

PS: Может всё-таки наконец-то открыть учебник по си и освоить хотя бы азы программирования на нём?

Узнать какие типы памяти бывают в си, что такое "указатели" и т.п.

 

On 11/11/2023 at 3:52 PM, EdgeAligned said:

Обратите внимание на расположение локальных, локальных статических и глобальных переменных и поведение стека вызовов и видимость переменных в зависимости от вызванных функций. Представлен хронологический порядок (слева направо, сверху вниз) - main(), вызов ф-ции Foo1(), вызов из нее Foo2(), возврат в Foo1(), возврат в main(). Когда функция вызывается, указатель вершины стека смещается вверх (в сторону меньших адресов) и образуется область для размещения локальных переменных функции. При выходе из функции указатель вершины стека смещается вниз (в сторону возрастания адресов), и оставшиеся за его пределами переменные хоть физически и не уничтожаются, но становятся недействительными и будут перезаписаны при следующем вызове других функций.

2023-11-11203741.thumb.jpg.7b373b528f03d9d9708de3442cfe2910.jpg    2023-11-11204347.thumb.jpg.91611c9633d4a1401c3cc714e139c4b2.jpg

2023-11-11204432.thumb.jpg.7ddde43bc691a1acafcacb955addd1c6.jpg   2023-11-11204458.thumb.jpg.fc2dbe814c31b67afa1d9bf2c87bc34b.jpg

2023-11-11204527.thumb.jpg.e9af323b4029bda455d4b393fc7d88da.jpg

 

 

 

У меня  нет проблем с пониманием видимости классических переменных и указателей . Я очень редко работаю со строками и у меня вызывает вопрос только лишь этот вариант

char* srt = "hhh";

//---------------------------------

 

Можно ли УСЛОВНО разделить это выражение так

char* str = ( str_arr1[4] ={hhh} )

В данном случае компилятор создал строку из 3+1 байт и записал ее гдето в памяти например по адресу например  00cff9d4

этот адрес мы передали указателю str

т.е по сути  это эквивалентно такому

char* str;

 str_arr1[4] ={hhh} ;

str =str_arr1;

 

Теперь самое интересно , если выше все так  то адрес  00cff9d4   сейчас хранится ТЛОЬКО в  указателе str !!

и если мы туда запишем другой адрес то  получим утечку памяти??  Ведь строка  {hhh} ; все ще существует ДО КОНЦА ПРОГРАМЫ(или бока) но адреса ее мы уже не знаем и использовать ее уже не можем??

 

 

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

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


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

Еще одна картинка: (поскольку запускаю отладку из SRAM, то вся программа вместе с текстом и константами находится тоже в RAM, в её начале. Но если запустить из флеша, то это поместится во флеш). 

 

Снимок экрана 2023-11-11 211304.jpg

строка с массивом символов находится в секции .rodata, то есть является константным неизменяемым значением. А указатель на строку указывает на первый адрес этого константного массива, но ячейка указателя помещается в области стека.

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


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

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

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

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

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

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

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

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

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

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