Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/124: Рейтинг темы: голосов - 124, средняя оценка - 4.73
640KB мне хватило на всё.
119 / 50 / 3
Регистрация: 07.06.2009
Сообщений: 442
1

char *s или char s[]

17.08.2011, 15:52. Показов 24119. Ответов 16

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
  char s1[]="1111",s2[]="2222";
  printf("%s %s\n",s1,s2);
  memmove(s1,s2,2);
  printf("%s %s\n",s1,s2);
работает нормально
C++
1
2
3
4
  char *s1="1111",*s2="2222";
  printf("%s %s\n",s1,s2);
  memmove(s1,s2,2);
  printf("%s %s\n",s1,s2);
компилируется с предупреждением
warning: deprecated conversion from string constant to 'char*'
и при запуске падает из-за memmove. Что собственно в этом плохого?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.08.2011, 15:52
Ответы с готовыми решениями:

Преобразование char в char* или разделить на две строки
Пытаюсь сделать программу под linux. Возникла проблема, описанная в заголовке. Мне нужно разделить...

Приведение массива char[] (или char* ) в LPCTSTR
Задача: пользователь вводит директорию, нужно проверить существует ли эта директория. Функция...

Char unsigned char signed char длинна Кааак
Здравствуйте. char l = {0,0}; l = 0xff; Почему, меня, компилятор не посылает куда...

string[] в char[][] или char[]
Приветствую! Можно ли одномерный массив типа string переписать в двумерный или одномерный типа...

16
return (true);
1976 / 1111 / 221
Регистрация: 19.04.2011
Сообщений: 2,345
17.08.2011, 15:54 2
Выделение памяти
0
Higher
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
17.08.2011, 15:55 3
В 1 случае память статически выделяется, во-втором просто объявляется указатель без всякого выделения памяти. А это не есть хорошо.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.08.2011, 16:07 4
Выражение "1111" имеет тип const char *, вы же пытаетесь присвоить его переменной типа char *, отсюда предупреждение. Падает программа из-за memmove, поскольку, как уже было сказано, "1111" - константная строка и её нельзя изменить.
0
640KB мне хватило на всё.
119 / 50 / 3
Регистрация: 07.06.2009
Сообщений: 442
17.08.2011, 16:32  [ТС] 5
Если s1 указатель на не-константу, то почему вообще возможна запись?
char *s1="что-то там";
И почему падает memcpy? Ну передали две ссылки на a и b, сказали сколько байт надо скопировать, а падать зачем?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.08.2011, 16:34 6
Цитата Сообщение от skvor Посмотреть сообщение
то почему вообще возможна запись
Неявное преобразование типа.
Цитата Сообщение от skvor Посмотреть сообщение
падать зачем
Потому что константы неизменны по определению.
0
Заблокирован
17.08.2011, 16:41 7
Цитата Сообщение от skvor Посмотреть сообщение
C++
1
2
3
4
  char s1[]="1111",s2[]="2222";
  printf("%s %s\n",s1,s2);
  memmove(s1,s2,2);
  printf("%s %s\n",s1,s2);
работает нормально
C++
1
2
3
4
  char *s1="1111",*s2="2222";
  printf("%s %s\n",s1,s2);
  memmove(s1,s2,2);
  printf("%s %s\n",s1,s2);
компилируется с предупреждением

и при запуске падает из-за memmove. Что собственно в этом плохого?
Во-втором случае вы инициализируете указатель значением, который указывает на строковый литерал. Согласно стандарту С++ строковый литерал имеет тип const char[], то есть массив констатных символов. Стандарт оставляет способ размещения литералов на усмотрение производлителей компиляторов. Например, совпадающие по значению литералы, то есть дублирующиеся литералы могут храниться в виде одного литерала. В свыязи с этим представьте себе такой код

C++
1
2
3
4
5
6
7
char *p = "Lex";
 
*p = 'S";
...
...
if ( strcmp( s, "Lex" ) == 0 )
/* и.т.д. */
Вы думаете, что с помощью функции strcmp вы сравниваете символьный массив 's' со значением "Lex", а на самом деле так как компилятор совпадающие строковые литералы может хранить в виде одного строкового литерала, то вы будете сравнивать не с "Lex", а с "Sex", так как строковый литерал был изменен!

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

В первом же случае, когда вы объявляете массив, то нимкакого строкового литерала в памяти не создается. Создается массив, который инициализируется значением выражениям инициализации. То есть в данном случае

char s1[]="1111";

создается массив s1, элементы которого получают значения '1', '1', '1', '1', '\0'. А сам строковый литерал, используемый в качестве выражения инициализации в памяти программы не сохраняется.
0
640KB мне хватило на всё.
119 / 50 / 3
Регистрация: 07.06.2009
Сообщений: 442
17.08.2011, 17:06  [ТС] 8
Не имеет значения то на что указывает ссылка - константа или не-константа.
Ссылка указывает на участок памяти, и в программе этот участок никак не маркируется.
Если ссылка на константу, то сам компилятор не должен разрешать выражения меняющие значение.
При запуске программы по ссылке s1 находится пять байтов "1111\0". То что данные взяты из константного выражения уже не имеет значения - s1 является указателем на char.

Добавлено через 4 минуты
Сыроежка, пожалуйста, читайте внимательно, а не по диагонали через пять строк.
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.08.2011, 17:08 9
skvor, я не понимаю, чего вы добиваетесь? Вам уже сказали причину - строковый литерал располагается в read-only памяти, менять такую память запрещено, попытка приводит к печальным последствиям. Вы хоть указатель на int установите указывать на эту read-only память, результат будет всё тем же плачевным. Важно не то, какой тип имеет указатель, а то, какой тип имеет объект, на который этот указатель указывает.

Добавлено через 1 минуту
И не надо ваших предположений по поводу того, что компилятор должен делать и чего не должен. Они могут оказаться чрезвычайно далеки от истины.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
17.08.2011, 17:16 10
Цитата Сообщение от skvor Посмотреть сообщение
Если ссылка на константу, то сам компилятор не должен разрешать выражения меняющие значение.
Если внимательно посмотреть на предупреждение, то можно увидеть там слово deprecated. Это наследие старины глубокой, скорее всего даже из языка Си пришедшее. Это неявное преобразование рады бы запретить, но если делать это сразу, то сломается довольно много старого кода. Вы же всегда можете включить опцию компилятора, которая считает предупреждения ошибками, тем более что часто это так и есть, как и в данном случае.
2
Заблокирован
17.08.2011, 20:55 11
Цитата Сообщение от skvor Посмотреть сообщение
Не имеет значения то на что указывает ссылка - константа или не-константа.
Ссылка указывает на участок памяти, и в программе этот участок никак не маркируется.
Если ссылка на константу, то сам компилятор не должен разрешать выражения меняющие значение.
При запуске программы по ссылке s1 находится пять байтов "1111\0". То что данные взяты из константного выражения уже не имеет значения - s1 является указателем на char.

Добавлено через 4 минуты
Сыроежка, пожалуйста, читайте внимательно, а не по диагонали через пять строк.
Я совершенно не понял, что вас не устроило в моем ответе! Не можете ли разъяснить, чем вы не довольны?!

Добавлено через 5 минут
Цитата Сообщение от grizlik78 Посмотреть сообщение
Если внимательно посмотреть на предупреждение, то можно увидеть там слово deprecated. Это наследие старины глубокой, скорее всего даже из языка Си пришедшее. Это неявное преобразование рады бы запретить, но если делать это сразу, то сломается довольно много старого кода. Вы же всегда можете включить опцию компилятора, которая считает предупреждения ошибками, тем более что часто это так и есть, как и в данном случае.
На самом деле это не неявное преобразование, а явное! Я понимаю, что вы мне сейчас сделаете ссылку на приложение D стандарта, где говорится о неячвном преобразовании. Но на самом деле в другом месте стандарта говорится, что такое преобразование может иметь место только при явном преобразовании! Это одно из тех мест стандарта, где стандарт сам себе противоречит.
Что значит "явное преобразование"? Это преобразование вида
C++
1
chat *p = "ABC";
То есть вы явно указываете тип результирующего выражения.

При неявном преобразовании строковый литерал как раз преобразуется в выражениях (кроме ссылок на них) в
C++
1
const char *
.
0
grizlik78
17.08.2011, 21:00
  #12

Не по теме:

Цитата Сообщение от Сыроежка Посмотреть сообщение
На самом деле это не неявное преобразование, а явное!
Ну и зануда же, а? Слово неявное в моём сообщении вообще никакой роли не играло.

1
Заблокирован
17.08.2011, 21:37 13
Цитата Сообщение от grizlik78 Посмотреть сообщение

Не по теме:


Ну и зануда же, а? Слово неявное в моём сообщении вообще никакой роли не играло.

Если слово никакой роли не играет , то и не следует им засорять речь!
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
17.08.2011, 21:43 14
Преобразование там, конечно же, неявное, что ж с этим поделать-то? Почему же на основании чьих-то заблуждений я должен выкидывать слово из предложения? Но если читателю оно не по душе, он может смело его выкинуть, смысл от этого нисколечко не изменится.
Кроме того, говоря "Это неявное преобразование" я подразумевал не только выражение типа
C++
1
char const *s = "abc";
но и выражение
C++
1
some_func("abc");
где в прототипе используется тип char*. Или в этом месте преобразование тоже явное?
0
Заблокирован
17.08.2011, 21:49 15
Цитата Сообщение от grizlik78 Посмотреть сообщение
Преобразование там, конечно же, неявное, что ж с этим поделать-то? Почему же на основании чьих-то заблуждений я должен выкидывать слово из предложения? Но если читателю оно не по душе, он может смело его выкинуть, смысл от этого нисколечко не изменится.
Кроме того, говоря "Это неявное преобразование" я подразумевал не только выражение типа
C++
1
char const *s = "abc";
но и выражение
C++
1
some_func("abc");
где в прототипе используется тип char*. Или в этом месте преобразование тоже явное?
Второе выражение тоже является явным преобразованием так как параметры вычисляются на основе оператора присваивания. То есть этот пример полностью аналогичен первому, если у функции параметр объявлен как char *.

Как я уже ранее отметил, в этом вопросе в стандарте присутствует путаница. Я все же согласен с тем, что когда явно указывается тип результата, как в операторе присваивания, или в объявлении, то это явное преобразование.
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
17.08.2011, 21:50 16
Хотелось бы увидеть ссылку на то место в стандарте, которое позволяет трактовать это таким образом.
0
4866 / 3288 / 468
Регистрация: 10.12.2008
Сообщений: 10,570
18.08.2011, 03:53 17
Цитата Сообщение от Сыроежка
На самом деле это не неявное преобразование, а явное!
явное преобразование типа - это через операцию приведения типа

C
1
char *p = (char *) "abcd";
это сработает без предупреждения, так как не отбрасывается const

операция присваивания имеет ряд ограничений
C89 (draft) 3.3.16.1 Simple assignment
* both operands are pointers to qualified or unqualified versions of
compatible types, and the type pointed to by the left has all the
qualifiers of the type pointed to by the right;
0
18.08.2011, 03:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.08.2011, 03:53
Помогаю со студенческими работами здесь

Ошибка: "char *concat(char *,.)": невозможно преобразовать аргумент 1 из "const char [4]" в "char *"
делал задание, но на строке 36 строке пишет, что "char *concat(char *,...)": невозможно...

(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&
astxx::manager::connection::connection(std::basic_string&lt;char, std::char_traits&lt;char&gt;,...

Error C2664: sprintf: невозможно преобразовать параметр 1 из 'const char *' в 'char *'
error C2664: sprintf: невозможно преобразовать параметр 1 из 'const char *' в 'char *' void...

Ошибка в cannot convert char * to char вроде поправил теперь выводит ересь(
Всем доброго дня! У меня такая проблемка.... написал программу, но сначала она ругалась на Cannot...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru