Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/107: Рейтинг темы: голосов - 107, средняя оценка - 4.54
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
1

В чем разница между char* и char[]?

01.10.2014, 18:28. Показов 21139. Ответов 69
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток, наткнулся на одну загвоздку есть такой кусок кода
C++
1
2
3
4
5
6
7
8
int _tmain(int argc, _TCHAR* argv[])
{
    char *a = "111111111111";
    *((int*)a+1) = 0;
    std::cout<<a;
    system("pause");
    return 0;
}
и такой
C++
1
2
3
4
5
6
7
8
int _tmain(int argc, _TCHAR* argv[])
{
    char a[] = "111111111111";
    *((int*)a+1) = 0;
    std::cout<<a;
    system("pause");
    return 0;
}
запускаем в виже, первый кусок эксепшн
второй норм. Разъясните пожалуйста
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.10.2014, 18:28
Ответы с готовыми решениями:

В чем разница между char* и char **
в чем разница между char* и char ** ??

Разница между char и signed char
Не понимаю в чем разница между char и signed char, ведь char по умолчанию знаковый. Не...

Разница между char[] и char*
Здравствуйте. Провожу небольшую иследовательскую работу по выяснении разницы между char и char*....

Разница между new char[] и new char[]()
Доброго времени суток. Подскажите пожалуйста разницу, между следующим кодом: char* ch = new...

69
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,712
01.10.2014, 21:24 21
Author24 — интернет-сервис помощи студентам
Рекомендую посмотреть пост по ошибке такого рода:
Распространенные ошибки
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
01.10.2014, 22:13  [ТС] 22
всем спасибо, сегодня сходу не смог разобраться в этом...жалко, а все достаточно очевидно
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
01.10.2014, 22:14 23
Цитата Сообщение от zss Посмотреть сообщение
Рекомендую посмотреть пост по ошибке такого рода:
Распространенные ошибки
Убеждённый не с этим спорил. Он спорил с тем, должен ли компилятор выдавать ошибку. Деление на ноль - это код, который приведёт к слому на исполнении. Но компилятор там не должен выдавать ошибку. Так и здесь

P.S. А за то, что собрали распространённые ошибки в одно место - это вы просто молодцы. Главное, чтобы не гнались за количеством, а то оно превратится в помойку, которую не осилит ни один начинающий программист

Добавлено через 44 секунды
А по теме вопроса - на всякий случай ссылка: https://www.cyberforum.ru/blogs/18334/blog97.html
1
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
01.10.2014, 22:23 24
Цитата Сообщение от Evg Посмотреть сообщение
Так и здесь
Нет не так. В С++ система типов строже чем в С, и константность без явного приведения снять нельзя (пункт стандарта я уже указал выше). С другими типами, отличными от char (и wchar_t), такое уже не пройдет.
C++
1
2
3
4
5
6
int main()
{
    const int a[100] = {};
    int * p = a;
    return 0;
}
А в случае char - это поблажка для legacy, унаследованного из С и достандартных версий С++.
А вот в С такое запросто можно делать.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
01.10.2014, 22:35 25
Действительно, ремарку про Си++ я как-то проморгал. Убеждённый так же пример проверял на Си
0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
16844 / 6723 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
01.10.2014, 22:48 26
Цитата Сообщение от Evg Посмотреть сообщение
Убеждённый так же пример проверял на Си
Нет, на C++11, там на сайте справа указывается
http://ideone.com/PfKPOq
язык: C++11
Просто там по дефолту отображение предупреждений отключено, в сообщении https://www.cyberforum.ru/post6670223.html это видно..
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
01.10.2014, 23:19 27
Цитата Сообщение от KOPOJI Посмотреть сообщение
Нет, на C++11, там на сайте справа указывается
А... я что-то посмотрел на надпись "Deputy C Compiler", подумал, что там Си
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
01.10.2014, 23:26 28
Цитата Сообщение от DrOffset Посмотреть сообщение
Я не называл GCC неадекватным, еще раз говорю. Я сказал, что если компилятор не способен выдать варнинг на такой случай, то только тогда он неадекватный. Разница есть?
Я против навешивания ярлыков "адекватный-неадекватный" на основании одного примера.

Цитата Сообщение от DrOffset Посмотреть сообщение
Пункт 4.4/1. Константность неявно снимать нельзя.
Признаю, был неправ.
Компилятор, которым пользуется ТС, в данном вопросе ведет себя неадекватно.
0
18841 / 9840 / 2408
Регистрация: 30.01.2014
Сообщений: 17,281
01.10.2014, 23:46 29
Цитата Сообщение от Убежденный Посмотреть сообщение
Я против навешивания ярлыков "адекватный-неадекватный" на основании одного примера.
Мне кажется с твоей стороны нет желания понять, что я имел в виду. Объясню еще раз:
1) Компилятор должен соответствовать стандарту.
2) Компилятор может вносить свои расширения. И даже включать их по умолчанию.
3) Компилятор должен иметь средства эти расширения отключить.
4) Или компилятор должен иметь средства показать пользователю, что используются нестандартные расширения.
Если все эти пункты не выполняются, то компилятор не адекватен. Яркий пример: Borland C++ 3.1.
С чего ты вдруг решил, что я навешиваю какие-то ярлыки, мне не понятно.

Добавлено через 8 минут
Еще раз приведу цитату:
Цитата Сообщение от DrOffset Посмотреть сообщение
б) если компилятор нормальный - включай в нем диагностику.
Это это, очевидно, значит, что я и не собирался навешивать ярлыки. Я предположил одновременно, что компилятор может быть как адекватным, но с отключенной диагностикой (что ты продемонстрировал на примере ideone.com), так и неадекватный. Как из двойственности этого утверждения следует, что я навесил ярлык?
Когда навешивают ярлык, говорят безапелляционно. Без рассмотрения двух противоположных случаев.

Не по теме:

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

0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
02.10.2014, 00:38 30
aLarman,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string.h>
using namespace std;
void foo( char *c){
cout<<c<<endl;
}
int main()
{
//вот автоматический (стековый) массив, он создаётся на стадии компиляции:
    char arr_inited_by_list[] = {'a', 'b', 'c', '\0'}; //список инициализации нужен компелятору, чтобы знать сколько памяти
    //на стэке выделить и что туда поместить. 
    //Эта запись полностью аналагична первой:
char arr_inited_by_string_literal[] = "abc";
//создаются они одинаково, то есть литерал - информация компилятору и переменная для него не создаётся
cout<<arr_inited_by_list<<endl;
cout<<arr_inited_by_string_literal<<endl;
//а вот указатель, он служит для хранения адреса начала участка памяти, где лежит связанная с ним переменная,
//но сам выделить эту память он не может. Это наша забота и давайте ему поможем выделив её в куче:
char * ptr_to_arr_in_dynamic_mem = new char[strlen(arr_inited_by_string_literal)+1];
strcpy(ptr_to_arr_in_dynamic_mem, arr_inited_by_string_literal);
cout<<ptr_to_arr_in_dynamic_mem<<endl;
//то есть печать указателя char на консоль (и куда угодно) это печать содержимого массива на к-рый он указывает
//для указателя на int всё было бы иначе. Это никого не делает счастливее, но так сложиось. Верней сложилоСи))
 
//а вот указатель на строковый литерал:
char * ptr_to_string_literal = "abc";
//дело в том, что компилятору в этом случае нет прямого указания как и где выделять память под переменную на которую указывает
//указатель. Он начинает справа и создает переменную (постоянную)) - строковая константа и это может быть в секции
//read_only, а потом устанавливает указатель на начало этого участка.
// Это тоже от Си.
cout<<ptr_to_string_literal<<endl;
//строго говоря, в этом нет какой-то скрвытой логики. Просто так сложилось и это нужно запомнить
 
//о функциях, указателях и константности:
//Можно легко создать константный указатель (указатель на константу, но так принято говорить хоть и неверно)) на неконстантную
//переменную и это не делает переменную константой. Это не позволяет модифицировать переменную, именно по данному указателю:
const char * ptr_to_const = ptr_to_arr_in_dynamic_mem;
//а теперь попробуем передать его в функцию где параметр определён как простой указатель:
//foo( ptr_to_const);
//раскоментируйте и увидете, что это не компилируется!
//но многие библиотеки Си определены именно так, хотя они не модифицируют переданную переменную
//и для совместимости разрешается неконстантный указатель связывать с константой. )) 
 system ("pause");
 return 0;
}
1
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
02.10.2014, 11:24  [ТС] 31

Не по теме:

IGPIGP, спасибо, я уже прочитал про стр.литералы :)



Добавлено через 1 час 56 минут
кстати, gcc 4.8.2 вывод
Bash
1
2
3
4
main.cpp: In function ‘int main()’:
main.cpp:4:12: warning: deprecated conversion from string constant to ‘char*[-Wwrite-strings]
 char * a = "111";
            ^
с -w понятно без предупреждения
0
IGPIGP
02.10.2014, 12:38
  #32

Не по теме:

Цитата Сообщение от aLarman Посмотреть сообщение
IGPIGP, спасибо, я уже прочитал про стр.литералы
Дык и я прочитал. Дело в том, что когда я решил наваять, в теме было затишье. С моим зрением такой постик требует немного времени. :pardon: А когда подключился и разместил, увидел 2-ю страницу и ссыль на блог Evg. Так что многое совпало. :pardon: Ну то есть между char* и char[] разница в том, что это совершенно разные вещи. А инициализация указателей и массивов строковыми литералами, действительно отличает указатели и массивы char от указателей и массивов любого другого встроенного типа. И вдобавок их инициализация сильно отличается между собой при сходности синтаксиса. Это настоящий праздник для новичка, поэтому имхо: к чарам стоит приступать, когда тема указатели и массивы для других встроенных типов от зубов отскакивает.
Не прозвучало ещё и то, что указатель на char это указатель на один символ (оно вроде и понятно, но в терминологии часто встретишь - строка, массив и имеет смысл, это акцентировать для новичков) и то что массивы char, это не всегда c-строки, а c-строки это всегда массивы char. В целом статья Evg - очень хороша. Удачи. :)

0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.10.2014, 13:04 33
Цитата Сообщение от IGPIGP Посмотреть сообщение
Не прозвучало ещё и то, что указатель на char это указатель на один символ
Строго говоря, это не верно. Указатель - он просто указатель в какой-то адрес памяти. А на какое количество char'ов он указывает - про это ведает только программист, обычный процессор про это ничего не знает. Т.е. в данном примере

C
char a[4] = { 'a', 'b', 'c', '\0' };
char b;
 
char *p1 = a;
char *p2 = &b;
с точки зрения процессора и компилятора указатели p1 и p2 принципиально ничем не отличаются
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
02.10.2014, 13:20 34
Цитата Сообщение от Evg Посмотреть сообщение
Строго говоря, это не верно
Очень даже верно. Указатель может указывать на char ( const char * ), а может указывать на массив из n элементов ( const char[n] * )

C++
1
2
3
  const char foobar[] = "xxx";
  const char* x = foobar;
  const char( *y )[ _countof( foobar ) ] = &foobar;
0
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
02.10.2014, 14:05 35
Цитата Сообщение от Voivoid Посмотреть сообщение
а может указывать на массив из n элементов
это уже указатель на указатель получается, а там говорилось о простом указателе на char.
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
02.10.2014, 14:14 36
Цитата Сообщение от КОП Посмотреть сообщение
это уже указатель на указатель получается
Не, это именно что указатель на массив. Указатель на указатель на char - const char **
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
02.10.2014, 14:27 37
Цитата Сообщение от Voivoid Посмотреть сообщение
Указатель может указывать на char ( const char * ), а может указывать на массив из n элементов ( const char[n] * )
А ещё может указывать на int и на float. Я знаю.

Если отбросить сарказм, то при чём тут указатель на массив char'ов, когда было русским языком сказано про указатель на char. Ну и, если вдруг ты не знаешь, то указатель на char и указатель на массив char'ов - это две разные вещи (точно так же, как указатель на char и указатель на int)
1
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
02.10.2014, 17:02 38
Цитата Сообщение от Evg Посмотреть сообщение
с точки зрения процессора и компилятора указатели p1 и p2 принципиально ничем не отличаются
И это значит, что char * это указатель на один символ. Далее функция которая заточена под строки будет искать терминатор, а не заточенная, - не будет. Указывая на символ внутрь строки - получим символ или подстроку начинаемую этим символом. То есть указывать это указывать на символ, а как этот адрес интерпретировать, это не дело указателя.

Цитата Сообщение от Evg Посмотреть сообщение
Если отбросить сарказм, то при чём тут указатель на массив char'ов, когда было русским языком сказано про указатель на char
Абсолютно согласен. Указатель на массив это уже третье. А массисв типа и указатель на тип, новички часто путают. Массив это имя которое неявно преобразуется к указателю Type * const. То есть его нельзя использовать в правой части выражений адресной арифметики или инкрементировать, но в левой - везде где ожидается указатель, такое имя можно использовать или передать аргументом в функцию, где формальный параметр - указатель. Вообще, нюансов столько, что можно час говорить и неделю охать: -" Эх, ещё то надо было... и вот об этом забыли...".
0
Tulosba
02.10.2014, 17:14
  #39

Не по теме:

Цитата Сообщение от IGPIGP Посмотреть сообщение
То есть его нельзя использовать в правой части выражений адресной арифметики или инкрементировать, но в левой - везде где ожидается указатель,
наоборот же

0
Комп_Оратор)
Эксперт по математике/физике
8949 / 4703 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
02.10.2014, 18:48 40
Цитата Сообщение от Tulosba Посмотреть сообщение
наоборот же

Да, лево и право перепутал. Хотел:
<<То есть его нельзя использовать в левой части выражений адресной арифметики или инкрементировать, но в правой - везде где ожидается указатель...>>

Я помню, длиннющий холивар, где я и Croessmah, говорили о том, указатель ли это на символ или на массив. Тогда я, кстати, доказывал, что на массив, а Саша твёрдо отстаивал классическую точку зрения. Он говорил, что на символ, потому как разыменование даёт символ и потому, что синтаксически и пр. А похоже на массив потому, что так перегружены операторы сдвига потоков, написаны библиотеки, но это же не компилятор... Я злорадствовал, что если у плюсов отрезать std и библиотеки включая iostream то это будет С--, для которого придётся всё другое написать и это легче, чем кого-то потом убедить, что это тоже С++ и им можно пользоваться.
Добивающим доводом, если я верно помню, было то, что несмотря на то, что большинство операторов (==, >, + и пр.) перегружены как для символа, но оператор [] сделан так, что имя указателя можно использовать как имя массива для индексного обращения к памяти как к массиву типа. И при этом неважно инициализирован указатель (в куче) указателем на массив памяти - new char[] или одним new char.
Это верно не только для указателей на char ().
И кто был прав? Строго говоря, - оба (имхо). Это место в языке достаточно противоречиво и тут главное не спорить, а понять что хотел сказать оппонент.

Не по теме:

Тогда мы с Сашей и подружились.


В чём смысл подобных разговоров? Думаю в том, чтобы побудить новичков вернуться к простым типам, если они не уверены, что массивы и указатели знают хорошо, перед тем как взяться за чары. И в том, чтобы напомнить опытным, что может быть непонятно новичку в этой теме.
0
02.10.2014, 18:48
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.10.2014, 18:48
Помогаю со студенческими работами здесь

(char)xx и '\xx' - в чём разница?
День добрый. Просто любопытно, почему cout &lt;&lt; (char)число; и cout &lt;&lt; '\число'; часто дают...

Разница между char и int
Известно что для чар выделяется 1 байт (8 бит) для инт 4 байта (32 бита). Так почему нельзя в чар...

Строка: чем отличается строки string, char, char*?
Помогите разобраться,совсем плохо идёт,чем отличается строки string,char,char* И если можно пару...

Чем отличается const char* от char*?
Доброго всем дня! Из матчасти я понимаю, что char* - это указатель массив символов, тогда как...


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

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