![]() |
|
Модераторы: bsa |
![]()
|
|
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
char* arr[3] = {"str1", "str2", "str3"};
Почему во всех примерах, использования массива указателей на строки, память, для каждой, не выделяется оператором new? Я ожидал что то вроде этого: (Псевдокод)
Это сообщение отредактировал(а) lv151 - 31.1.2009, 11:44 |
|||
|
||||
| Avaj |
|
||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 212 Регистрация: 14.7.2008 Где: Владивосток. Репутация: 1 Всего: 3 |
Тут объявляется массив из константных строк, а для них память самостоятельно выделять не надо, но также их нельзя изменять, т.е. например так:
По-моему так. |
||||
|
|||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
Это массив указателей на строки.
|
|||
|
||||
| pan2004 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 357 Регистрация: 28.7.2007 Репутация: 2 Всего: 9 |
указатели не обязательно означают, что объект, на который они указывают, будет находится в heap.
В твоем примере создается массив указателей на стековую область памяти, поэтому никакого new. так тоже можно, но надо не забыть потом сделать delete |
|||
|
||||
| Avaj |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 212 Регистрация: 14.7.2008 Где: Владивосток. Репутация: 1 Всего: 3 |
lv151,
|
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
указатели не обязательно означают, что объект, на который они указывают, будет находится в heap.
В твоем примере создается массив указателей на стековую область памяти, поэтому никакого new Это только для переменных символьного типа? Это сообщение отредактировал(а) lv151 - 31.1.2009, 14:09 |
|||
|
||||
| Christoph |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 667 Регистрация: 23.1.2008 Где: Харьков Репутация: нет Всего: 11 |
это указатель на область памяти, которая представлена как последовательность символов -------------------- ![]() |
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
ОК.
Почему char* arr[3] = {"str1", "str2", "str3"} - это прокатывает, а это - int* i = 5 (или int* i;*i = 5;), нет. Это сообщение отредактировал(а) lv151 - 31.1.2009, 18:13 |
|||
|
||||
| mes |
|
||||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
почему нет ? это скомпилируется, просто в рантайме вызовет ошибку записи не в свою память вот так правильней:
ну вы пытаесь указатель вместо адресса, на какой он должен указывать пропихнуть обыкновенное значение. если Вам действительно нужно такое, надо предупредить компилятор, что Вы знаете, чего делаете:
ну а если нужен массив, то пишите так
Это сообщение отредактировал(а) mes - 31.1.2009, 18:53 |
||||||
|
|||||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
||||
|
||||
| mes |
|
||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
потому что в Вашем сравнении Вы сравниваете разные вещи. *i = 5; - запись в ячейку по разъименованому указателю.
Это сообщение отредактировал(а) mes - 31.1.2009, 19:53 |
||||
|
|||||
| lv151 |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
Да, я понимаю что char c[] - это адрес, т.е. указатель константа, char * s - указатель - переменная, но мы можем таким же образом работать и с int:
или
char* p = 'a'; - а это не запись в ячейку по разъименованому указателю? так почему char* p = 'a', а так нет - int* p = 1; указатели не обязательно означают, что объект, на который они указывают, будет находится в heap. В твоем примере создается массив указателей на стековую область памяти, поэтому никакого new Почему для int* p = 1 не выделяется память в стеке, а на уровне компиляции: error C2440: 'initializing' : cannot convert from 'int' to 'int *' Это сообщение отредактировал(а) lv151 - 31.1.2009, 20:52 |
||||
|
|||||
| mes |
|
||||||||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
оба примера не будут компилироваться Добавлено через 1 минуту и 18 секунд
это нет, а
Добавлено через 11 минут и 28 секунд
Вы путаетесь в уровнях, попробую зайти немного с другой стороны. вот Вам три однотипных инициализации массивов:
все выглядит абсолютно одинаково- Вас устраивает ? только для компилятора string это char * , поэтому третья строчка записывaется так :
|
||||||||||
|
|||||||||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
0) char *x = "asdq" - работает, char *x = {'a', 's', 'd', 'q'} - нет. Для удобства в компиляторе есть встроенный
механизм работы со строками? 1) Т.Е. для компилятора char x[5] = "asdq" равно char *x = "asdq"?, только во втором случае мы можем менять адрес переменной? 2) Компилятор сам выделяет память? 3) Как он получает адрес переменной? Это её адрес в "теле exe-ника"? Это сообщение отредактировал(а) lv151 - 31.1.2009, 22:23 |
|||
|
||||
| mes |
|
||||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
ага есть, правда примитивный, но польза большая.
нет, в первом случае вы создаете массив и инициализируете его строкой, а во второй вы получаете указатель на строку хранящаюся в сегменте данных. char x[5] // компилятор создает на стеке массив из 5 элементов = "asdq"; // и копирует в него эту строку char *x = "asdq"; // тут ничего не выделяется в рантайме
какой переменной ? адрес строки ? грубо говоря да. |
||||||
|
|||||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
1) char *x = "asdq" – в данном случае значением указателя является адрес переменной в сегменте данных, который получаем во время компиляции? Правильно я понял? 2) А если переменная не глобальная? fun() { char x1[5] = "aaaa"; char *x = "asdq"; } При вызове функции "aaaa" помещается в стек, после, строка "asdq". Значением x является вершина стека? т.е. стек выглядит так? значение адрес asdq 04 aaaa 05 х = 04? |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
почти .. во время компиляции получаем смещение, а реальный адрес получается в момент рантайма, путем прибавления смещения к адрессу сегмента. во время компиляции эти строки ложатся в сегмент данных, а в рантайме указатели инициализируются адресом этой строки, а массивы данными той строки из сегмента данных. стек выглядит примерно так : нач.адреес значение кон.адрес 00 asdq\0 04 // x1[5] = 05 0x.... 08 // где 0х... адрес строки 5 байт на массив, и 4 на указатель (для обычных (х86) 32хбитных машин, при условии отсутствия выравнивания на стеке.. но это смысла не меняет) Это сообщение отредактировал(а) mes - 1.2.2009, 13:19 |
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
вовсе не обязательно, в случе с указателем строка может быть помещена в любой read only сегмент, а может и не быть помещена. Во втором случе я вообще причн не вижу хранить строку, оставить ее в стеке и не марать сегмент данных вовсе. |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
||||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
Посоветуйте, что можно почитать по данной теме.
|
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
а причем тут рантайм? это не рантайм |
|||
|
||||
| GoldFinch |
|
|||
![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2141 Регистрация: 30.11.2008 Репутация: 6 Всего: 26 |
mes, хз как у С++ а в делфи константы кладутся в сегмент кода, сразу за телом функции в которой они используются
|
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
инициализация массива x1(заполнение стека) происходит в рантайме.
также, зависит от компилятора и места где определены данные (глобально или в функции) в нашем случае сегмент данных, и данные в сегменте кода означает одно и то же, "данные хранящиеся в теле "ехешника" " и с точки зрения языка неразличимы. Это сообщение отредактировал(а) mes - 1.2.2009, 14:43 |
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
Посоветуйте литературу по данной теме.
Это сообщение отредактировал(а) lv151 - 1.2.2009, 15:16 |
|||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
давай не будет понятия подменять, нет там никакого рантайма. Все известно на этапе компиляции. с точик зрения языка вообще никаких сегментов нет, так, что ты изначально не прав. Добавлено через 1 минуту и 1 секунду книжки по С\С++ любые, огбсуждения книжек идут в прикрепленном топике |
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
||||
|
||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
||||
|
||||
| mes |
|
||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
давай.. и так когда происходит создание и инициализация массива ? размер которого и содержание (точнее сказать образ) известны на этапе компиляции.
я про обязательное наличие сегментов и не утверждал, было лишь употреблено для легкого понимания не вид, ни место хранения данных, которыми заполняется массив не важен. Важно, что компилятор сохраняет строку в теле программы в "удобном" (зависимом от контекста использования) виде, и 1. при создании массива использует содержимое этой строки для инициализации стека, 2 а при инициализации указателя используется адрес этой строки |
||||
|
|||||
| vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
в рантайме, но для языка это рантаймом не является потому, как не зависит ни от каких внешних факторов и всегда статично. |
|||
|
||||
| mes |
|
||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
т.е инициализация стека происходит в рантайме, но рантаймом не является.. так ? интересно.. так данные в стек помещаются на этапе компиляции ? если нет , то откуда берутся ? или я неправильно трактую Ваше высказывание ? :
Это сообщение отредактировал(а) mes - 1.2.2009, 16:38 |
||||
|
|||||
| vinter |
|
||||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
именно так, не надо путать языковый рантайм с реальным. Я еще раз повторяю, для языка это не является рантаймом. Для языка рантаймом является: выделение памяти, исключения и т.д. Но уж точно не стек.
ступил. Строку хранить надо. |
||||
|
|||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
работа со стеком тоже является рантаймом. не является рантаймом смещение переменной в стеке, и данные для инициализации, по которым в некоторых случаях компилятор может догадаться о реальном содержимом стека. |
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
||||
|
||||
| Arden |
|
||||||||||||
|
Новичок Профиль Группа: Участник Сообщений: 20 Регистрация: 23.1.2009 Где: Украина, Волынь Репутация: нет Всего: нет |
Показалась тема похожей, поэтому новой создавать не стал. Есть вот такой код:
Программа компилируется и запускается нормально. Инициализирую массив и когда входит в цикл, программа выдает ошибку с текстом:
Если использовать в цикле вместо указателя char *p массив char p[20], то программа работает. Возникло несколько вопросов: 1) Почему тогда например код
работает, а практически такой же код в цикле - нет? 2) Часто встречаю примеры типа:
Это вообще нормально? Куда указывает указатель *p до момента его инициализации? 3) В чём разница между строчками
и
Я так понимаю, что а всегда указывает на 1 элемент массива, а p можно сместить, например с помощью инкремента. Я правильно понял? А в чём еще разница? Надеюсь я нормально выразился. Только недавно начал учить программирование, дошел до строчек и тут немножко запутаться. Это сообщение отредактировал(а) Arden - 3.2.2009, 20:06 |
||||||||||||
|
|||||||||||||
| pan2004 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 357 Регистрация: 28.7.2007 Репутация: 2 Всего: 9 |
Arden, вообще код имхо ужасный изза подобных операций над двумерным массивом. Не стал разбираться, потому что думаю, ты там что-то напутал. например, если a массив типа char[5][20], то куда будет указывать a+1? Явно не туда, куда ты думаешь) Не путай здесь массивы с указателями, разные это вещи.
1) Сомневаюсь, что даже этот код работает - p указывает в пустоту. 2) Это нормально. Пофиг, куда указывает p до вызова strcat - он инициализируется этой функцией. (если интересно, до этого он указывает на случайный адрес, но здесь это ни на что не влияет) 3) вот так советуют ни в коем случае не делать! Может создаться впечатление, что это указатель на неконстантную строку, но, увы, это не так. При попытке изменить ее будет UB(программа вылетит скорее всего). Если уж так, то пиши const char*. более-менее аналогично
|
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
||||
|
||||
| Arden |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 20 Регистрация: 23.1.2009 Где: Украина, Волынь Репутация: нет Всего: нет |
Да вроде как не напутал. Программа должна 5 введенных строк упорядочить по алфавиту. Алгоритм практически такой же, как при сортировке пузырьком. Для сравнения двух стрингов использую функцию strcmp(a, b). Если a>b, то меняю их местами.
a+1 будет указывать на начало второй строчки, тоесть на элемент a[1][0].
Работает. Я бы не рвался сразу на форум, не помучив голову самому себе сначала Тоесть с "пустыми" указателями желательно не работать? Именно это меня и смутило, в книге нашел полно таких примеров |
||||
|
|||||
| mes |
|
||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
желательно не работать? С неинициализированными указателями НЕЛЬЗЯ работать.
а не второго столбца ? Делает вид , что работает из за случайного стечения обстоятельства, потому что система не всегда может определить запись в чужую память. Это сообщение отредактировал(а) mes - 4.2.2009, 15:19 |
||||
|
|||||
| Arden |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 20 Регистрация: 23.1.2009 Где: Украина, Волынь Репутация: нет Всего: нет |
||||
|
||||
| Arden |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 20 Регистрация: 23.1.2009 Где: Украина, Волынь Репутация: нет Всего: нет |
А как вывести адрес области, на которую указывает указатель типа char? Ведь при
и
мы получим символ и строку соответственно, а как получить сам адрес так как при других типах? |
||||
|
|||||
| MAKCim |
|
||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 2 Всего: 207 |
-------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||
|
|||||
| Arden |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 20 Регистрация: 23.1.2009 Где: Украина, Волынь Репутация: нет Всего: нет |
MAKCim,
спасибо. |
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
Нашёл ответ одним предложением:
Компилятор неявно выполняет преобразование const_char из const char[N] в char*(char* str = "String"). Это сообщение отредактировал(а) lv151 - 8.2.2009, 11:25 |
|||
|
||||
| pan2004 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 357 Регистрация: 28.7.2007 Репутация: 2 Всего: 9 |
lv151, лучше бы он этого не делал. Избавление от const обычно требует const_cast<>.
Хотя, gcc дает предупреждение:
|
|||
|
||||
| lv151 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 916 Регистрация: 11.2.2008 Репутация: нет Всего: 2 |
Это С++, в С другой механизм. Наверно, тоже основан на приведении типов.
|
|||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |