char* a против char a[]
От: Аноним  
Дата: 12.02.06 11:02
Оценка:
В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.
Re: char* a против char a[]
От: DigitalGuru Россия http://svetlyak.ru
Дата: 12.02.06 11:09
Оценка: :)
Здравствуйте, Аноним, Вы писали:

А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.


Правильнее было бы назвать тему так:
"char* a против char a[], и они оба против std::string"
Re: char* a против char a[]
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 12.02.06 11:18
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае 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"; //массивы в языке С не могут стоять слева от =. Поэтому ты и получаешь сообщение об ощибке.


А вообще -- совет:
1) используй std::string.
2) Смотри http://rsdn.ru/article/cpp/cstr.xml
Автор(ы): Сергей Аристов
Дата: 28.12.2003
Это первая часть, в которой обсуждаются «традиционные» строки в С. В С++ существуют более удобные механизмы для работы со строковыми данными, эти механизмы рассматриваются во второй части статьи. А зачем вообще обсуждать неудобные С-строки, если есть С++? К сожалению, совсем забыть о строках в стиле С нельзя по двум причинам:
1. существует большое библиотек (например, API операционных систем) работающих именно с С-строками
2. строковые классы в С++ все равно основаны на традиционных С-строках, и если мы хотим разобраться в том, как они работают, нам придется понимать их основы.
Re[2]: char* a против char a[]
От: kan_izh Великобритания  
Дата: 12.02.06 11:31
Оценка:
BitField wrote:
> char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0').
> char * x = "abcd"; //эквивалентно
В каком смысле? Выражение типа x[2]='e' в первом случае вполне законно, а во втором — неопределённое поведение.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: char* a против char a[]
От: kan_izh Великобритания  
Дата: 12.02.06 11:32
Оценка:
kan_izh wrote:

>> char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4

> текста и последний '\0').
>> char * x = "abcd"; //эквивалентно
> В каком смысле? Выражение типа x[2]='e' в первом случае вполне законно,
> а во втором — неопределённое поведение.
Ой, торможу, сорри.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: char* a против char a[]
От: sch  
Дата: 12.02.06 13:26
Оценка: 4 (2)
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

const char *txt1 = "^^Test^^";
const char txt2[] = "^^Test^^";

int main(int argc, char* argv[])
{
const char *a1 = txt1;
const char *a2 = txt2;
}



; 19 : const char *a1 = txt1;

; здесь -- две операции: считываем адрес из переменной в регистр и записываем в другую переменную
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



Также может быть интересно сравнить:

const char *txt1 = "^^Test^^";
const char txt2[] = "^^Test^^";

int main(int argc, char* argv[])
{
txt1 = "123"; // txt1 -- переменная, писать в нее мы можем
txt2 = "123; // txt2 -- константа, т.е. адрес строки
}
Re[2]: char* a против char a[]
От: Elich  
Дата: 12.02.06 13:28
Оценка:
BF>char x[] = "abcd"; //равносильно обьявлению массива из 5 символов (4 текста и последний '\0').
BF>char * x = "abcd"; //эквивалентно

Попутный вопрос:

extern const char Text1[]       = "Text1";
extern const char * const Text2 = "Text2";

template<const char* T>
class TestClass
{
public:
  TestClass()
  {
    std::cout << T << "\n";
  }  
};

int main()
{
  TestClass<Text1> class1; // Ok
  TestClass<Text2> class1; // [b]<!-- MSVS 7.1 error C2975: 'T' : invalid template argument for 'TestClass', compile-time evaluatable constant expression expected
}


Почему для const char * const invalid?
Re[3]: char* a против char a[]
От: Elich  
Дата: 12.02.06 13:43
Оценка:
E>Почему для const char * const invalid?

Вопрос отпал. Спасибо предвидцу sch.
Re[3]: char* a против char a[]
От: Аноним  
Дата: 12.02.06 19:24
Оценка:
Здравствуйте, sch, Вы писали:


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[] создается массив символов, а в другом случае тоже он создается?
Re[3]: char* a против char a[]
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 13.02.06 08:38
Оценка:
Здравствуйте, sch, Вы писали:


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).
Re[5]: char* a против char a[]
От: kan_izh Великобритания  
Дата: 13.02.06 10:16
Оценка:
Аноним 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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: char* a против char a[]
От: LordAhriman  
Дата: 13.02.06 11:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.

вот ещё ОГРОМНАЯ разница:

size_t sz1 = sizeof(str)/sizeof(str[0]);
size_t sz2 = sizeof(str2)/sizeof(str2[0]);
Re[2]: char* a против char a[]
От: Аноним  
Дата: 13.02.06 12:43
Оценка:
Здравствуйте, LordAhriman, Вы писали:

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


А>>В чем принципеальная раздница между этими объявлениями переменных? Почему в первом случае cin>>a не проходит, а во втором проходит; почему в 1 a = "dsfs" проходит, а во 2 нет.

LA>вот ещё ОГРОМНАЯ разница:

LA>
LA>size_t sz1 = sizeof(str)/sizeof(str[0]);
LA>size_t sz2 = sizeof(str2)/sizeof(str2[0]);
LA>



Спасибо всем за ответы. Очень помогли. Стало намного понятней. Но есть еще один момент. Если char *s это указатель, то почему возможно обращение s[0] и почему нельзя заменить одиночный символ, хотя обратиться можно?
Re[3]: char* a против char a[]
От: Аноним  
Дата: 13.02.06 13:43
Оценка:
Здравствуйте, Аноним, Вы писали:

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


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


A> почему в 1 a = "dsfs" проходит — все становится просто если помнить, что вы объявили указатель.


Да и еще. Почему проходит присвоение a = "dsfs", это ведь указатель, а не ссылка?
Re[3]: char* a против char a[]
От: kan_izh Великобритания  
Дата: 13.02.06 14:20
Оценка:
Аноним wrote:
> Спасибо всем за ответы. Очень помогли. Стало намного понятней. Но есть
> еще один момент. Если char *s это указатель, то почему возможно
> обращение s[0] и почему нельзя заменить одиночный символ, хотя
> обратиться можно?
Читай мой ответ. потому что a[]="" выделяет массив на стеке каждый раз, когда входишь в блок, а *a="" указатель на
массив, бог (компилер, т.е.) знает где выделенный.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.