![]() |
|
Модераторы: bsa |
![]()
|
|
| mrgloom |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
передаю в функцию NULL, в функции выделяю память и хочу вернуть обратно измененный массив.
не могу понять почему, ведь я передаю указатель, причем когда память выделяется "сверху" функции, то всё как и ожидается т.е. когда
Добавлено @ 14:17
так тоже работает. или это всё специфика передачи массива? Это сообщение отредактировал(а) mrgloom - 20.8.2013, 14:54 |
||||||
|
|||||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
mrgloom, указатель, фактически, это такая переменная, которая хранит адрес. Когда ты вызываешь какую-то функцию и передаешь ей какой-то параметр, то в ней создается новая переменная (имя и тип ее указаны в скобках после имени функции), которой присваивается переданное в качестве параметра значение. Таким образом, когда ты меняешь эту переменную, ты меняешь только ее, а не источник значения на входе функции.
когда ты указываешь программе использовать ссылку или указатель на переменную (в твоем случае переменная - указатель на char), то ты можешь поменять значение источника. |
|||
|
||||
| SenkraD |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
дело в том mask - это копия указателя. тоесть она указывает туда же, куда и оригинальный, но адресс у него другой, тоесть это другой указатель:
Вывод:
Это сообщение отредактировал(а) SenkraD - 20.8.2013, 14:55 |
||||||
|
|||||||
| mrgloom |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
ну это всё понятно, вопрос как передать указатель на пустой массив, внутри функции выделить память для него, заполнить и потом выдать обратно(чтобы переданный указатель указывал но новый массив).
получается что нужно передавать указатель по ссылке? или указатель на указатель? вообщем тут вот ответ http://www.codeproject.com/Articles/4894/P...ence-to-Pointer получается что передавая указатель на массив мы можем изменять начинку массива, но не можем изменять переданный указатель, а при выделении памяти заново внутри функции мы как раз меняем указатель. |
|||
|
||||
| SenkraD |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
кстати, это не мешает вам удалить то, на что указывает указатель:
Это сообщение отредактировал(а) SenkraD - 20.8.2013, 15:09 |
||||
|
|||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
по-хорошему, лучше так не делать. Удалять надо там же, где и выделять. Иначе потом можно кучу проблем огрести.
mrgloom, посмотри описание функции realloc. Такой подход тоже можно использовать. |
|||
|
||||
| SenkraD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
ну это с тех времен, когда смарт поинтеры еще были не так популярны или их нельзя было использовать или их не было в проекте. Плюс несколько раз приходилось писать кустомный делетеры для boost::shared_ptr |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
SenkraD, мое замечание в основном касалось конкретного примера. Естественно, что при использовании умных указателей заморачиваться не надо (хотя, если память выделяется в библиотеке, то и освобождаться должна там же).
|
|||
|
||||
| SenkraD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
Ну, собсвенно, такие функции часто бывают в библиотеках:
|
|||
|
||||
| NoviceF |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
||||
|
||||
| mrgloom |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
как раз с delete[] похоже и выявилась проблема, долго не мог понять в чем дело, потом нашел
похоже в моем случае это связано как раз с dll, как решаются такие проблемы? самое простое вроде как передавать std::vector<std::vector<char>> еще заметил что если сделать так
то массив вроде как зануляется (?) , а я всего лишь хотел приравнять первый элемент к нулю. это наверно связано с тем, что массив char воспринимается как строка? |
||||
|
|||||
| SenkraD |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
ну да дебагер ее видит как строку, но сам массив не зануляется.
в чем именно это выраженно? общее правило при работе с dll такие:
Это сообщение отредактировал(а) SenkraD - 21.8.2013, 11:14 |
||||
|
|||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
Никак. В С и С++ массив (точнее область памяти), выделенный с помощью new и/или malloc, уже не может изменить свой размер. Так что сколько вы ему памяти при создании дали, столько в нем и будет, и никакая функция этого изменить не сможет. Что же касается функции realloc, то она как ни странно не увеличивает размер массива, а содает новый массив (по другому адресу), и копирует в него содержимое старого массива. Т.е. адрес массива после нее может измениться. |
|||
|
||||
| akizelokro |
|
||||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Добавлено через 3 минуты и 56 секунд А может и не измениться Добавлено через 7 минут и 45 секунд И вообще здесь начните с объяснения, как в С просто передаются параметры в функцию. Я просто навскидку уже знаю один вариант, как менять содержмое массива внутри функции, даже не передавая туда значение. С помощью глобальных переменных и решая вопрос с, например, видеопамятью, которая начинается по фиксированному адресу. Добавлено через 13 минут и 51 секунду
сам стиль плох. потому что вызовом new(malloc и т.д.) уже в одну строчку выделяется память Это сообщение отредактировал(а) akizelokro - 24.8.2013, 13:59 -------------------- a = a + b; b = a - b; a = a - b; |
||||
|
|||||
| aleksandrkr |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.9.2013 Репутация: нет Всего: нет |
давай мыслить логически как выглядит переменная. переменная состоит из двух частей [адрес в памяти][значение]
передаётся в функцию по копии то есть, создаётся копия переменной. что такое указатель это тоже самое, только во второй части у него лежит адрес. что передаётся в функцию если переменная ровна нулю, правильно делается копия. но значение у нас ноль [адрес в памяти][NULL]; в это 0 мы выделяем память, то есть там не ноль а адрес. вот тут и получается прикол что твоя переменная ( p ) понятия не имеет о выделенной памяти у неё значение 0; в копию мы выделили память а в переменной так и осталось значение 0; рассуждаем дальше что нам надо для того чтоб можно было выделить память, нужно сделать указатель на указатель то есть нужно чтоб сюда в значение попал адрес переданной переменной [адрес в памяти][значение]. и получается что-то такого типа [адрес копии][адрес переданного указателя][значение переданного указателя (не копия)]. вот вам два способа как этого добиться:
Это сообщение отредактировал(а) aleksandrkr - 19.9.2013, 14:17 |
|||
|
||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Это очень смелое утверждение -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| aleksandrkr |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.9.2013 Репутация: нет Всего: нет |
да я с вами согласен я не совсем точно объяснил, точнее я немного исказил реальность дабы донести суть проблемы до новичка.
правда на самом деле в переменной хорониться только адрес в памяти. int P = 10; cout << &P <<endl; //адресс cout <<P <<endl; //значение; http://www.firststeps.ru/asm/r.php?35 Это сообщение отредактировал(а) aleksandrkr - 19.9.2013, 17:23 |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Это в указателе хранится адрес. А вот массив - это не указатель. Он может быть приведен к указателю (явно или не явно). Но фактически это единая переменная. Переменная - это просто набор данных в памяти. И естественно, известен ее адрес. Другое дело, что адрес может ВЫЧИСЛЯТЬСЯ в процессе работы программы или может быть вшит в нее жестко. Поэтому утверждение о том, что переменная состоит из двух частей имеет столько же смысла, сколько: "моя квартира состоит из двух частей: адрес и помещение". |
|||
|
||||
| aleksandrkr |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.9.2013 Репутация: нет Всего: нет |
1)переменная типа массив это указатель на его первый элемент.
int arr[10] ={0}; int * p = arr + (sizeof(int) * 4) ; аналогично записи arr[4]; 2)int pr; эта запись в процессе компиляции будет заменена на asm { MODEL SMALL STACK 256 DATASEG Data1 DB 31h ; выделить один байт с содержимым 31h CODESEG Start: mov ax,@data ; установка в ds адреса mov ds,ax ; сегмента данных mov ax,OFFSET Data1 ; где находиться переменная End Start } компилятор сам просчитает где ляжет переменная и везде где он встретит pr он заменит pr на полученный адрес 0xbfd86d6c Указатель — это переменная, содержащая адрес некоторого элемента данных (переменной, константы, функции, структуры). В языке C указатели тесно связаны с обработкой массивов и строк Бьерн Страуструп. Язык программирования С++ 1.3.2 Переменные и арифметические операции Каждое имя и каждое выражение обязаны иметь тип. Именно тип определяет операции, которые могут выполняться над ними. Например, в описании int inch; говорится, что inch имеет тип int, т.е. inch является целой переменной. Описание - это оператор, который вводит имя в программу. В описании указывается тип имени. Тип, в свою очередь, определяет как правильно использовать имя или выражение. Основные типы, наиболее приближенные к "аппаратной реальности" машины, таковы: char short int long Они представляют целые числа. Следующие типы: float double long double представляют числа с плавающей точкой. Переменная типа char имеет размер, нужный для хранения одного символа на данной машине (обычно это один байт). Переменная int имеет размер, необходимый для целой арифметики на данной машине (обычно это одно слово). Следующие арифметические операции можно использовать над любым сочетанием перечисленных типов: + (плюс, унарный и бинарный) - (минус, унарный и бинарный) * (умножение) / (деление) % (остаток от деления) То же верно для операций отношения: == (равно) != (не равно) < (меньше чем) <= (меньше или равно) >= (больше или равно) Для операций присваивания и арифметических операций в С++ выполняются все осмысленные преобразования основных типов, чтобы их можно было неограниченно использовать любые их сочетания: double d; int i; short s; // ... d = d + i; i = s * i; Символ = обозначает обычное присваивание. 1.3.3 Указатели и массивы Массив можно описать так: char v [ 10 ]; // массив из 10 символов Описание указателя имеет такой вид: char * p; // указатель на символ Здесь [] означает "массив из", а символ * означает "указатель на". Значение нижней границы индекса для всех массивов равно нулю, поэтому v имеет 10 элементов: v [ 0 ] ... v [ 9 ]. Переменная типа указатель может содержать адрес объекта соответствующего типа: p = & v [ 3 ]; // p указывает на 4-й элемент массива v Унарная операция & означает взятие адреса. |
|||
|
||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Ну вот зачем такое писать -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| aleksandrkr |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.9.2013 Репутация: нет Всего: нет |
точно извиняюсь sizeof лишний
Добавлено через 7 минут и 20 секунд у кого нибудь стоит 6 студия. проверти эту запись. short * p = arr + 4; оно правильно отработает или нет. Добавлено через 8 минут и 44 секунды по идеи оно работать не должно. |
|||
|
||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
-------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Это не так. Массив ведет себя аналогично указателю в большинстве случаев. Но в ряде случаев он отличается: передача массива в качестве параметра шаблонной функции, sizeof. Поэтому нельзя говорить, что массив это указатель. |
|||
|
||||
| volatile |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
||||
|
||||
![]()
|
| Правила форума "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. |