| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Передать в функцию char* |
| Автор: Competitor 18.5.2006, 12:32 | ||
Как передать char* s в функцию в качестве модифицируемого параметра, т.е. чтобы после выполнения следующего кода:
на экран выводилось "Привет". |
| Автор: _hunter 18.5.2006, 12:34 |
| передавать char** (или ссылку на char*) |
| Автор: likehood 18.5.2006, 12:35 | ||
можно так:
т.е. передаешь ссылку на указатель. |
| Автор: Helicopterr 18.5.2006, 13:13 | ||
| Competitor сделай так:
|
| Автор: Romikgy 18.5.2006, 13:20 | ||
А так разве нельзя? |
| Автор: likehood 18.5.2006, 13:28 |
| нельзя |
| Автор: Romikgy 18.5.2006, 14:50 |
| baronp, чего? |
| Автор: likehood 18.5.2006, 15:18 |
это был короткий ответ на твой предыдущий пост. Объясняю почему нельзя: хоть tem и является указателем, это еще не значит, что его изменение даст эффект за пределами функции. Изменить можно только то, на что он указывает, а изменение самого указателя изменит лишь его локальную копию в данной функции. Внешний же указатель s при этом не изменится. Поэтому я и посоветовал в своем первом посте использовать ссылку на указатель. Главное не забыть освободить память, которая выделяется в функции func, но это уже другой разговор. |
| Автор: gruy 18.5.2006, 15:47 |
| Romikgy, в твоем примере general при выходе из функции удалится. |
| Автор: likehood 18.5.2006, 16:11 |
| запусти свой вариант, убедись что не работает. Поставь между tem и звёздочкой амперсанд в прототипе функции и убедись что работает. Еще раз подумай почему. |
| Автор: Romikgy 18.5.2006, 16:51 |
| Каюсь уже убедился, только нафига тогда придумали приставку const |
| Автор: likehood 18.5.2006, 17:09 |
| ты имеешь ввиду const перед указателем или const в конце прототипа функции? |
| Автор: Earnest 18.5.2006, 19:45 | ||
Путаешь теплое с мягким... Вот пример:
Как думаешь, изменится N после вызовы foo? Вот и с указателем то же самое: если переменная передается по значению, она копируется и меняется только ее копия (внутри функции), снаружи все сохраняется... То, что вместо int у тебя указатель, ничего не меняет: его значение меняется только внутри функции. |
| Автор: Romikgy 19.5.2006, 08:27 |
Это я уже понял, мне интересно на кой тогда делать такой вызвов void foo (const int a) Ведь всеравно , что внутри менялось в наружу не выдет? зачем надо было так извращатся то? |
| Автор: Daevaorn 19.5.2006, 09:05 | ||
Для самоконтроля программиста. Чтобы ненароком не записать в эту переменную что-либо. Но по сути, пользы от этого мало. |
| Автор: Romikgy 19.5.2006, 09:28 |
| Я смотрю в С много чего есть , правда пользы от него маловато, зато когда начинаешь об этом читать, голова может сварится |
| Автор: likehood 19.5.2006, 10:28 | ||||
Польза все же есть, вот пример:
Если оставить все как есть, получим ошибку компиляции: нельзя изменить значение по указателю s в функции func. Если же const убрать, получим Best string. |
| Автор: Fazil6 19.5.2006, 10:41 | ||||
не все так просто и очевидно. Ты написал функцию int fffff(char* s); теперь я пишу программу и применяю твою функцию. Я знаю, что часто указатель передается в функцию для того, чтобы туда был записан результат. Я не знаю как и что делает эта ф-я и я не знаю что будет лежать по этому указателю после вызова этой функции. А вот если ты напишешь функцию int fffff(const char* s); у меня никаких сомнений нет по поводу того зачем передается указатель. Тоже самое относится и к аргументам ссылкам. |
| Автор: Romikgy 19.5.2006, 10:55 | ||
И зачем? |
| Автор: Fazil6 19.5.2006, 11:06 | ||
затем, что это аргумент для функции, а не буфер для результата. Затем, что передача ссылки(указателя) намного эфективнее чем передача значения при передаче классов/структур и классы обычно так и передаются |
| Автор: Romikgy 19.5.2006, 12:11 | ||
это с этим как то не соотносятся в чем эффективнее? |
| Автор: Fazil6 19.5.2006, 12:43 | ||||
хорошо. Начнем с конца.
допустим нам в функцию надо передать std::string можно так void fun(std::string str) а можно и так void fun(std::string* str) результат будет одинаковый и в первом и во втором случае внутри функции мы получим необходимую строку, но в первом случае будет создан еще один объект, в этот объект будут копироваться все значения полей (все, что определено в конструкторе копии), а во втором будет передано значение адреса и все. Вызов второго варианта намного быстрее.
прекрасно соотносится. В нашем 2-м варианте я не могу знать зачем передается указатель просто из соображений эфективности или для того, чтобы записать что-то по этому адресу, а если будет стоять const, то это значит, что функция говорит, что она не собирается изменять содержимое по этому адресу и буфером для результата это не является |
| Автор: Любитель 19.5.2006, 13:00 |
| Функции вида void func(const int a) действительно бессмысленны. const нужно для ссылок и указателей, чтобы гарантировать, что мы с помощью этой ссылки или указателя не изменим значение. НО для указателя - указываемое значение, а не значение самого указтеля. |
| Автор: Romikgy 19.5.2006, 13:32 | ||||
Окей здесь вышло недопонимание терминов, об этом я знал давно
А с этим как то не совсем соглашусь, ты когда нибудь смотрел ассемблер код такой функции с const и без оной? Посмотри ... он ничем не отличается |
| Автор: Earnest 19.5.2006, 13:38 |
| Именно это Fazil6 и говорит. const практически не влияет на сгенерированный код, это подсказка для программиста и компилятора. |
| Автор: Fazil6 19.5.2006, 13:50 | ||
я и не заявляю, что const влияет на эфективность. я говорю совершенно о другом. если аргументом функции является const std::string*, то я понимаю, что указатель передается только для того, чтобы не передавать сам объект по значению и данные менять не собираются, а если const не указан, то я буду предполагать, что внутри этой функции этот объект будут изменять и после вызова функции моя строка вполне возможно будет изменена. Т.е. в случае когда в аргументах функции встречается указатель на константу, то компилятору это значит "нельзя менять содержимое", а для программиста вызывающего эту функцию это говорит: "содержимое не будет меняться" |
| Автор: GremlinProg 19.5.2006, 14:00 |
| Romikgy, раз уж ты о ассемблере заговорил, то наверняка понимаешь, что такое вызов cdecl. При очень плотной оптимизации, значения параметров с модификатором const могут не сохраняться дополнительно в стеке, а использоваться уже в другой функции. А теперь подумай, что будет, если ты вот такой параметр изменил: следующая по коду функция примет как будто тот же параметр, но на самом деле он будет изменен предыдущим вызовом. Это единственный случай, когда нужно помнить о const в параметрах типа void foo(int c). Остальное уже все рассказали, повторяться не буду. PS: оптимизация в сторону скорости работает по такому принципу только если ты ставишь const, в остальных случаях, все необходимые параметры сохраняются в стеке отдельно. Поэтому не пытайтесь изголяться с преобразованиями типа *(TYPE*)&c, где c - константа, ни к чему хорошему это не приведет, особенно, если вы таки используете оптимизацию компилятора. Подробно по всем опциям оптимизации написано в MSDN'е. |
| Автор: Romikgy 19.5.2006, 15:15 | ||
Если честно то не сильно , я просто взял две фунции и посмотрел что получается на выходе.
не понял? Добавлено @ 15:17 Все более к этому склоняюсь здесь можно по подробнее , на что влияет и когда? |
| Автор: GremlinProg 19.5.2006, 15:45 | ||||
cdecl - то вызов функции с передачей параметров в стеке. Вызывающий оператор сам очищает стек после вызова, поэтому параметры, которые он передаёт функции он может использовать повторно. Это одно из преимуществ, которое и породило thiscall.
Под этим я и подразумевал:
|
| Автор: Romikgy 19.5.2006, 15:54 |
понятно , а как очистить стек из С++ с модификатором |
| Автор: GremlinProg 19.5.2006, 15:59 |
| не понял вопроса, зачем тебе нужно его очищать? |
| Автор: UnrealMan 20.5.2006, 10:06 | ||||
Помимо сказанного выше другими, добавлю. Если рассматривать const для ссылок, то он играет существенную роль. Например, если у тебя есть функция: void Func(char *&p), ты не сможешь передать ей по ссылке константную строку или строку-массив const char s1[] = "Text"; char s2[] = "Text"; Чтобы передать s1 (или просто "Text") либо s2, тебе придётся написать перед & слово const: void Func(char *const &p). Заодно ты запрещаешь изменение указателя p в своей функции. Для того, чтобы запретить ещё и изменение данных по этому указателю, надо дописать const где-то перед * void Func(const char *const &p). В случае передачи классовых объектов по ссылке без const у тебя не пройдёт ни одно неявное преобразование типа (к типам данных классов):
|
| Автор: GremlinProg 20.5.2006, 10:22 |
| UnrealMan, хорошее замечание! Про неявное преобразование я не знал |
| Автор: UnrealMan 20.5.2006, 11:23 | ||
Нда, и неклассовых, кстати, тоже:
Правда, экономить на времени передачи параметров простейших типов, нагромождая их описанием const &, в большинстве случаев будет излишеством :-) |