char* s = "test"; char s[] = "test"; объясните в чем разница
От: Аноним  
Дата: 25.04.03 12:14
Оценка:
здрасте,

char* s = "test"; // с этим делаю что хочу
char s[] = "test"; // это константа, по этому я с этим ничего не поделаю

объясните в чем разница,
спасибо
Re: char* s = "test"; char s[] = "test"; объясните в чем раз
От: Кодт Россия  
Дата: 25.04.03 12:40
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>char* s = "test"; // с этим делаю что хочу
А>char s[] = "test"; // это константа, по этому я с этим ничего не поделаю

А>объясните в чем разница,

В настройках компилятора и твоей неоправданной смелости

char* s = "test"
Это указатель на строку, которая расположена в сегменте статических данных.
Эквивалентно коду
static char _str_test[5] = { 't','e','s','t',0 };

char* s = _str_test;

Компилятор вправе создавать одинаковые строковые литералы либо раздавать указатели на один и тот же.
static char _str_test[5] = { 't','e','s','t',0 };

char* s = _str_test; // char* s = "test";
char* t = _str_test; // char* t = "test";


Модификация строкового литерала приводит к отдаленным последействиям. Например,
void f(char* s)
{
  if(strcmp(s, "test") == 0) printf("yes");
  else                       printf("no");
}

void g()
{
  char* t = "test";
  t[0] = 'b';
}

main()
{
  f("best"); // best != test --> no
  g(); // test заменили на best
  f("best"); // best == best --> yes
}

Поэтому компилятор С++ может (должен) считать, что строковый литерал имеет тип const char*.
Но для совместимости с голым Си это можно регулировать опциями.


Почему char s[] = "test" --- константа? Очень странно. Где-то у тебя очепятка.
... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
Re[2]: char* s = "test"; char s[] = "test"; объясните в чем
От: Аноним  
Дата: 25.04.03 14:51
Оценка:
Здравствуйте, Кодт, Вы писали:

<scip>
это понял

К>Почему char s[] = "test" --- константа? Очень странно. Где-то у тебя очепятка.

это отсутвие опыта(с++ — 3 месяца), почему-то думал что тип char всегда константный

почему так можно делать


char* s = "test";
s = "tost";
s = "testo";
s = "t";


а так нельзя


char s[] = "test";
s[2] = 'g'; //можно
s = "tost"; // no
s = "slkdjfsl"; //also no
Re[3]: char* s = "test"; char s[] = "test"; объясните в чем
От: Bell Россия  
Дата: 25.04.03 15:14
Оценка:
Здравствуйте, Аноним, Вы писали:

А>почему так можно делать


А>

А>char* s = "test";
А>s = "tost";
А>s = "testo";
А>s = "t";
А>


Указателю s по очереди присваиваются адреса разных строковых литералов. Ты ведь не имеешь ничего против такого кода:

int i= 0;
i = 30;
i = 2;



А>а так нельзя


А>

А>char s[] = "test";
//s имеет тип char[5], т.е. массив. При инициализации в него копируется литерал "test"
А>s[2] = 'g'; //можно
//третьему элементу массива присвоено новое значение
А>s = "tost"; // no; s имеет тип char[5], а "tost" - char*. Типы разные, соответственно и присваивание запрещено
А>s = "slkdjfsl"; //also no - см. выше
А>
Любите книгу — источник знаний (с) М.Горький
Re[3]: char* s = "test"; char s[] = "test"; объясните в чем
От: Кодт Россия  
Дата: 25.04.03 15:25
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>
А>char s[] = "test";
А>s[2] = 'g'; //можно
А>s = "tost"; // no
А>s = "slkdjfsl"; //also no
А>


Как присваивать строки и массивы.

1) строки: strcpy(куда, откуда) -- при этом "куда" должен иметь достаточно места.
2) POD (массивы и структуры простых данных): memcpy(куда, откуда, количество_байт)
3) хитрые данные — вручную или с использованием STL

Посмотри в документации (и в любом учебнике по Си) тему "работа со строками".
Там есть всякие нюансы.
Еще, возможно, тебе пригодится книга Язык Си в вопросах и ответах

Посмотри в книгах по С++ "стандартная библиотека шаблонов (STL)" — в ней есть реализации и массивов, и строк, и алгоритмов для них.
... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
Re[3]: char* s = "test"; char s[] = "test"; объясните в чем
От: jazzer Россия Skype: enerjazzer
Дата: 25.04.03 16:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Кодт, Вы писали:


<scip>
А>это понял

К>Почему char s[] = "test" --- константа? Очень странно. Где-то у тебя очепятка.

А>это отсутвие опыта(с++ — 3 месяца), почему-то думал что тип char всегда константный

А>почему так можно делать


А>

А>char* s = "test";
А>s = "tost";
А>s = "testo";
А>s = "t";
А>


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

А>а так нельзя


А>

А>char s[] = "test";
А>s[2] = 'g'; //можно
А>s = "tost"; // no
А>s = "slkdjfsl"; //also no
А>


а когда ты объявляешь массив, ты прямо на стеке выделяешь соответствующее количество байт, и s — имя этого объекта на стеке, а не указатель на него. Соответственно во второй строчке ты говоришь: "а измени-ка мне в этом объекте на стеке второй символ" — и это, естественно, пройдет, а вот в третьей и четвертой ты говоришь: "а пусть теперь s указывает на строковый литерал" — а что прикажете делать с объектом на стеке? Так что при таком объявлении s не может быть изменена, можешь относиться к ней как к имеющей тип char * const (т.е. константный указатель на неконстантную строчку).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: char* s = "test"; char s[] = "test"; объясните в чем
От: zeleniy  
Дата: 25.04.03 17:13
Оценка:
всем спасибо, прекрасно объяснили, и я все понял
Re: char* s = "test"; char s[] = "test"; объясните в чем раз
От: Jeff  
Дата: 25.04.03 18:00
Оценка:
Короче так:
char* s = "test": s — указатель, переменная, которая хранит адресс памяти.
В данном случае это адресс первого элемента массива символов ( если не знаешь, то массивы
в памяти непрерывны, т.е. фрагментации нет, типа один кусок там а другой здесь, потому,
массив можно выловить через указатель на его первый элемент ).

char s[] = "test": s — массив символов.

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

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

Преимущества использования указателей и ссылок: есть у тебя функция сортировки огромного массива
( ну допустим метров так 100 ). На сколько я знаю, нельзя из функции вернуть
массив ( возвращаемое значение ), но даже если тебе удастся это сделать, представь: когда
мы в эту функцию отдаем такой массив, то это приводит к выделению еще ста метров памяти —
функция создает копию массива. Вот. А если дать ссылку на массив, то функция не станет
создавать его копию, а станет работать с уже готовым.

Указатели вообще очень хорошая штука — в них вся мошь C++. Просто работота напрямую с
памятью быстрее, чем просто с переменными.

Еще один пример: оформил ты что-то в виде отдельного потока, но тебе надо использовать
некоторые функции из класса, создавшего этот поток. Берешь, и даешь потоку указатель
на самого себя (т.е. на класс) — this. А через указатель можно пробится к этим самым
функциям. Можно конечно тупо создать внутри потока объект класса, а если это, к примеру
главное диалоговое окно класса, и тебе в нем надо изменять значения некоторых переменных?
Например, пишешь ты копировщик файлов и функция копирования оформлена отдельным потоком
(так окно приложения не замораживается в ожидании завершения копирования),
а тебе же надо постоянно просматривать статус копирования... — через указатель достаешь
переменные класса окна и изменяешь их значения.

Конечно, во многих случаях можно обойтись и без указателей, но некоторые вещи без них
тяжело сделать, если вообще возможно.

Описание работы с указателями можно найти в любой книге по C++ для начинающих.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.