В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.
Здравствуйте, Аноним, Вы писали:
А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.
Правильнее было бы назвать тему так:
"char* a против char a[], и они оба против std::string"
Здравствуйте, Аноним, Вы писали:
А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.
char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0').char * x = "abcd"; //эквивалентноchar str[] = "abcd";
char * x = &str[0];
То есть обьявляется массив, на первый элемент которого указыват наша переменная.
если ты обьявляешь:
char str1[40]; //массив из 40 символов, который может хранить строку до 39 символов длинойchar *str2; //указатель на символ. Начиная с этого символа в памяти лежит строка. Но пока-что эта переменная указывает в мусор, в никуда.
str2 = "asdf"; //создали массив из 5 элементов (обычно компилятор заносит такой массив в секцию констант еще при компиляции).
//теперь str2 указывает на первый символ этого массива.
str1 = "aaaa"; //массивы в языке С не могут стоять слева от =. Поэтому ты и получаешь сообщение об ощибке.
BitField wrote: > char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0'). > char * x = "abcd"; //эквивалентно
В каком смысле? Выражение типа x[2]='e' в первом случае вполне законно, а во втором — неопределённое поведение.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
kan_izh wrote:
>> char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 > текста и последний '\0'). >> char * x = "abcd"; //эквивалентно > В каком смысле? Выражение типа x[2]='e' в первом случае вполне законно, > а во втором — неопределённое поведение.
Ой, торможу, сорри.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
BF>char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0'). BF>char * x = "abcd"; //эквивалентно
Эти две строки не эквивалентны, соответственно, весь остальной пост не имеет смысла.
extern const char * тоже работать не будет, т.к. эта константа не может быть вычислена во время компиляции.
Объявление const char *txt1 = "^^Test^^" говорит компилятору:
1) заведи переменную txt1
2) размести строку в памяти
3) запиши в txt1 адрес строки
Объявление const char txt2[] = "^^Test^^" говорит компилятору:
1) заведи строку
2) запомни ее адрес под именем txt2
; здесь -- две операции: считываем адрес из переменной в регистр и записываем в другую переменную
mov eax, DWORD PTR ?txt1@@3PBDB ; txt1
mov DWORD PTR _a1$[ebp], eax
; 20 : const char *a2 = txt2;
; здась -- одна операция, т.к. адрес txt2 является константой.
mov DWORD PTR _a2$[ebp], OFFSET FLAT:?txt2@@3QBDB ; txt2
BF>>char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0'). BF>>char * x = "abcd"; //эквивалентно sch>Эти две строки не эквивалентны, соответственно, весь остальной пост не имеет смысла.
sch>extern const char * тоже работать не будет, т.к. эта константа не может быть вычислена во время компиляции.
sch>Объявление const char *txt1 = "^^Test^^" говорит компилятору: sch>1) заведи переменную txt1 sch>2) размести строку в памяти sch>3) запиши в txt1 адрес строки
sch>Объявление const char txt2[] = "^^Test^^" говорит компилятору: sch>1) заведи строку sch>2) запомни ее адрес под именем txt2
sch>const char *txt1 = "^^Test^^"; sch>const char txt2[] = "^^Test^^";
sch>int main(int argc, char* argv[]) sch>{ sch> const char *a1 = txt1; sch> const char *a2 = txt2; sch>}
sch>; 19 : const char *a1 = txt1;
sch>; здесь -- две операции: считываем адрес из переменной в регистр и записываем в другую переменную sch> mov eax, DWORD PTR ?txt1@@3PBDB ; txt1 sch> mov DWORD PTR _a1$[ebp], eax
sch>; 20 : const char *a2 = txt2; sch>; здась -- одна операция, т.к. адрес txt2 является константой. sch> mov DWORD PTR _a2$[ebp], OFFSET FLAT:?txt2@@3QBDB ; txt2
sch>Также может быть интересно сравнить:
sch>const char *txt1 = "^^Test^^"; sch>const char txt2[] = "^^Test^^";
sch>int main(int argc, char* argv[]) sch>{ sch> txt1 = "123"; // txt1 -- переменная, писать в нее мы можем sch> txt2 = "123; // txt2 -- константа, т.е. адрес строки sch>}
Спасибо за подробный ответ, но тем не менее я не совсем понял. Ведь что в первом, что во 2 случае переменная-указатель содержит адрес первого символа.При char a[] создается массив символов, а в другом случае тоже он создается?
Re[4]: char* a против char a[]
От:
Аноним
Дата:
13.02.06 05:13
Оценка:
Здравствуйте, Elich, Вы писали:
E>>Почему для const char * const invalid?
E>Вопрос отпал. Спасибо предвидцу sch.
Спасибо за подробные ответы, но тем не менее я не совсем понял. Ведь что в первом, что во 2 случае переменная-указатель содержит адрес первого символа.При char a[] создается массив символов, а в другом случае тоже он создается?
Re[4]: char* a против char a[]
От:
Аноним
Дата:
13.02.06 05:15
Оценка:
Здравствуйте, Elich, Вы писали:
E>>Почему для const char * const invalid?
E>Вопрос отпал. Спасибо предвидцу sch.
Спасибо за подробный ответ, но тем не менее я не совсем понял. Ведь что в первом, что во 2 случае переменная-указатель содержит адрес первого символа.При char a[] создается массив символов, а в другом случае тоже он создается?
BF>>char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0'). BF>>char * x = "abcd"; //эквивалентно
sch>Эти две строки не эквивалентны, соответственно, весь остальной пост не имеет смысла.
А никто и не говорил, что эти две строки эквивалентны.
Прошу прощения, просто кривое форматирование
char * x = "abcd";
//эквивалентноchar str[] = "abcd";
char * x = &str[0];
Вы с этим не согласны?
Да, надо было еще указать на конст -- но морочить человеку голову неявным преобразованием const char [] в char * не хотелось
Re: char* a против char a[]
От:
Аноним
Дата:
13.02.06 10:00
Оценка:
Здравствуйте, Аноним, Вы писали:
А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.
Принципиальная разница в том, что в случае 1 вы объявляете указатель на char, а в случае 2 — массив char-ов.
Из-за того что в С/С++ строки реализуются как байтовые (или двухбайтовые) последовательности с нулем на конце,
получилась путаница указателей на char, массивов из char и собственно понятия строки.
Почему в первом случае cin>>a не проходит — потому что вы пытаетесь ввести значение указателя(!), ни строки, ни еще чего-нибудь.
Думаю вам не дадут ввести вообще никакой указатель на что-бы то нибыло.
а во втором проходит — потому что ввод массива из char определен, т.е. по-символьно.
Со второй частью интереснее.
почему в 1 a = "dsfs" проходит — все становится просто если помнить, что вы объявили указатель.
Строковй литерал "dsfs" сидит где-то в памяти по адресу ХХХ и занимает 5 байт.
Ваше присваивание присваивает указателю a адрес первого символа литерала, т.е. это адресс ХХХ.
Ни больше, ни меньше.
НО если это рассматривать в контексте строк, то это выглядитит как присвоение литерала строке.
а во 2 нет. — в этом случае вы массиву из char пытаетесь присвоить указатель на char,
потому что литерал представляется указателем.
Т.е. у вас в операции присваивания слева и справа разные объекты.
Массиву из char вы можете присвоить только другой массив из char, но не указатели (даже указатели на char).
Аноним wrote:
> Спасибо за подробный ответ, но тем не менее я не совсем понял. Ведь что > в первом, что во 2 случае переменная-указатель содержит адрес первого > символа.При char a[] создается массив символов, а в другом случае тоже > он создается?
Да, он создаётся компилером, обычно где-нидь внутрях, не на стеке, в "ресурсах".
И иногда бывает опция компилера: сделать pool строк.
Тогда выражение вида:
char *a = "asdf";
char *b = "asdf";
может быть a==b, если опция включена и a!=b если выключена.
Поэтому, раз c++, то лучше всегда писать:
const char *a = "asdf";
чтобы нечаяно не присвоить туда чего-нидь, иначе — ub.
но в записи
char a[] = "asdf";
a[1] = 'x';
ничего криминального нет.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Аноним, Вы писали:
А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.
вот ещё ОГРОМНАЯ разница:
Здравствуйте, LordAhriman, Вы писали:
LA>Здравствуйте, Аноним, Вы писали:
А>>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет. LA>вот ещё ОГРОМНАЯ разница:
LA>
Спасибо всем за ответы. Очень помогли. Стало намного понятней. Но есть еще один момент. Если char *s это указатель, то почему возможно обращение s[0] и почему нельзя заменить одиночный символ, хотя обратиться можно?
Re[3]: char* a против char a[]
От:
Аноним
Дата:
13.02.06 13:43
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, LordAhriman, Вы писали:
LA>>Здравствуйте, Аноним, Вы писали:
A> почему в 1 a = "dsfs" проходит — все становится просто если помнить, что вы объявили указатель.
Да и еще. Почему проходит присвоение a = "dsfs", это ведь указатель, а не ссылка?
Аноним wrote: > Спасибо всем за ответы. Очень помогли. Стало намного понятней. Но есть > еще один момент. Если char *s это указатель, то почему возможно > обращение s[0] и почему нельзя заменить одиночный символ, хотя > обратиться можно?
Читай мой ответ. потому что a[]="" выделяет массив на стеке каждый раз, когда входишь в блок, а *a="" указатель на
массив, бог (компилер, т.е.) знает где выделенный.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай