LINUX.ORG.RU

Си, использование присвоения

 


0

1
func1()
{
char *x;
...

x = "ABC";
...

func2(x);
}

вопрос к знатокам: правомерно ли такое присваивание/использование указателя x? во время присвоения строка «создается статически на стеке» или «непонятно где»?

пока в таком виде «все работает» (ну как говориться, возможно, пока... :о)

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

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

★★★★

Последнее исправление: sunjob (всего исправлений: 1)

Ответ на: комментарий от jo_b1ack

спасибо :о) а по вопросу?

правомерно ли такое присваивание/использование указателя x?

во время присвоения строка создается статически на стеке или «непонятно где»?

зы: сейчас я уже сделал «правильно», через выделение/освобождение памяти, но все-таки, хотелось бы уточнить!

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 1)

Строка «ABC» хранится где-то в памяти, создается при старте приложения.

x = «ABC»;

ты просто присваиваешь адрес этой строки переменной x, это будет работает, если ты дальше не попытаешься изменить строку через этот указатель

x[0] = 'a'; // тут может быть краш

anonymous
()
Ответ на: комментарий от anonymous

ну да... константу-то я забыл :о) спасибо за пендили

sunjob ★★★★
() автор топика
char *x;
...

x = "ABC";
x[0]='H'; //bad, bad, BAD

Литерал будет размещен в .rodata, попытка модификации приведет к UB

char x[] = "ABC"
x[0]='H'; //okay
Литерал будет размещен в .rodata и скопирован в стек, модифицировать можно.

Динамически выделять ничего не нужно, если время жизни char[] x равно времени жизни func1()

olelookoe ★★★
()
Ответ на: комментарий от olelookoe

да, ок! но в моем случае надо сначало обьявить, а потом, в зов-ти от «условия» либо присвоить «статическую строку», либо уже готовую строку в памяти...

sunjob ★★★★
() автор топика

вопрос к знатокам: правомерно ли такое ...

Тут ведь как. Такие примеры есть в книжках и лучше их читать. Изучать C по ЛОРу — плохая идея. Ведь сам вопрос и фундаментальный и одновременно один из тысяч других.

vodz ★★★★★
()
Ответ на: комментарий от vodz

когда кстати у царя выходит книжка?

anonymous
()
Ответ на: комментарий от i586

в данном случае вполне подходящий контекст, да и смысль...

п.с. по делу лучше высказывайтесь :о) спасибо

п.с.2 и да не присваевание - присваИвание

21 век обьявляется веком Пушкиныхь, ура... :о)

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 2)
Ответ на: комментарий от vodz

я не изучаю... а освежА-А-А-Ю... :о)

sunjob ★★★★
() автор топика

И не на стеке, и понятно где. Лучше бы почитал книжек

deadplace
()

вопрос к знатокам: правомерно ли такое присваивание/использование указателя x?

Нет. Тип строкового литерала - const char*, а вы присваиваете это char*.

во время присвоения строка создается статически на стеке или «непонятно где»?

Во время присвоения ничего не создаётся. И на стеке «статически» не бывает, стек динамический по своей природе. Строка размещается в сегменте статических данных исполняемого файла (это не стек). А на стеке лежит x, и в него кладётся константа, представляющая собой адрес строки.

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

Надо понять разницу между данными и указателем на них, для начала. А то что «надо» зависит от задачи. Если константную строку передавать - ничего не надо. Если нужна копия строки для, например, её изменения - то тогда аллоцировать память, копировать в неё строку и потом освобождать.

slovazap ★★★★★
()
Ответ на: комментарий от anonymous

И строго говоря, там char[]/const char[]. Привет сишным приведениям.

anonymous
()
Ответ на: комментарий от slovazap

Нет. Тип строкового литерала - const char*

Так и запишем — пятизвездочный эксперт опять опозорился.

anonymous
()
#include <stdio.h>

int main(void)
{
	char *x = "HELLO WORLD";
	printf("%p, %s\n", x, x);
	return 0;
}
$ ./a.out 
0x402010, HELLO WORLD
$ cat /proc/$(pgrep a.out)/maps
...
00402000-00403000 r--p 00002000 fd:01 11668078                           /tmp/a.out              <- строка тут
...
0171b000-0173c000 rw-p 00000000 00:00 0                                  [heap]                  <- Это куча
...
7fff7de62000-7fff7de84000 rw-p 00000000 00:00 0                          [stack]                 <- Это стэк
...

Строка была скопирована в память процесса прямо из исполняемого файла внутри куска байтов размером в 1 KiB. Это третий КиБ из исполняемого файла. Он скопирован на адрес 0x402000.

Смотрим исполняемый файл.

$ readelf --section-headers a.out
There are 30 section headers, starting at offset 0x4f80:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
...
  [15] .rodata           PROGBITS         0000000000402000  00002000  <- это тут
       0000000000000024  0000000000000000   A       0     0     8
...

Секция называется rodata (readonly data, данные только для чтения).

Какой-то хрен на хабре об организации виртуальной памяти процесса, больше нагуглишь сам.

anonymous
()
Ответ на: комментарий от i586

в этой стране именно что присвоение :)

anonymous
()
Ответ на: комментарий от anonymous

А может и не быть - если на микроконтроллере каком-нибудь без защиты областей памяти.

А может не быть и на писюке с линухом, в зависимости от флагов в эльфе и использования mprotect.

anonymous
()
Ответ на: комментарий от anonymous

хахахаха :) хаха =] ты хоть раз дебажил мк? там такие выкрутасы вытворяют, что „присвоение“ иммутабельной строки указателю на мутабельное очень даже мило выглядит =]

anonymous
()
Ответ на: комментарий от anonymous

уважаемые господа анонимы, давайте высказываться с примерамы/выкусами/выхлопами/кодом итд

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

спасибо

sunjob ★★★★
() автор топика
Ответ на: комментарий от anonymous

хахахаха :) хаха =]

Помню одно время был на лоре человек-смайлик, топил он за Lisp (и за C?), и против C++, вроде. Колоритный персонаж, в хорошем смысле этого слова — не то, что нынешнее племя. Это не ты, случаем?

anonymous
()
Ответ на: комментарий от sunjob

Тридцать два, тридцать два, два сброса, ноль два :)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.