char* или char[]
От: INsideR Латвия  
Дата: 02.01.04 09:32
Оценка:
Есть следующий код:

char* s = "Test";
s[2] = 'b';

У Страуструпа сказано, что это не верно, потому что char * указывает на строку с константными символами, надо писать так:
char a[] = "Test";

У меня в программе есть пару мест с char*, надо ли их переделывать?
Мудр тот, кто знает не многое, а нужное
Re: char* или char[]
От: Кирпа В.А. Украина  
Дата: 02.01.04 10:06
Оценка:
Здравствуйте, INsideR, Вы писали:

INR>Есть следующий код:


INR>char* s = "Test";

INR>s[2] = 'b';

INR>У Страуструпа сказано, что это не верно, потому что char * указывает на строку с константными символами, надо писать так:

INR>char a[] = "Test";

INR>У меня в программе есть пару мест с char*, надо ли их переделывать?


Да надо переделать так как советует Страуструп
Линкер может поместить эту строку в секцию с аттрибутом Readonly и запись в эту строку s[2] = 'b'; вызовет Access violation
типа память не может быть written
!0xDEAD
Re: char* или char[]
От: kliff Россия http://www.esignal.ru
Дата: 02.01.04 10:06
Оценка:
Здравствуйте, INsideR, Вы писали:

INR>Есть следующий код:


INR>char* s = "Test";

INR>s[2] = 'b';

INR>У Страуструпа сказано, что это не верно, потому что char * указывает на строку с константными символами, надо писать так:

INR>char a[] = "Test";

Неправильно и так и этак. По-любому нужно писать const.

const char * s = "Test";
const char s[] = "Test";


А разница в том, что во втором случае НЕ выделяется память под переменную-указатель.
Re[2]: char* или char[]
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 02.01.04 11:05
Оценка:
Здравствуйте, kliff, Вы писали:

[]

K>Неправильно и так и этак. По-любому нужно писать const.


K>
K>const char * s = "Test";
K>const char s[] = "Test";
K>


K>А разница в том, что во втором случае НЕ выделяется память под переменную-указатель.


Не вкурил про второй случай... Во втором случае вроде как таки резервируется кусок памяти и в него таки копируется содержимое строки... Это на случай если без const. Если с const — то более грамотные товарищи меня поправят...
Re: char* или char[]
От: A_lir  
Дата: 02.01.04 11:28
Оценка:
Здравствуйте, INsideR, Вы писали:

INR>char* s = "Test";

INR>s[2] = 'b';

INR>У Страуструпа сказано, что это не верно, потому что char * указывает на строку с константными символами, надо писать так:

INR>char a[] = "Test";

INR>У меня в программе есть пару мест с char*, надо ли их переделывать?


Создание указателя на Си-строку — некоректное объявление.
Лучше задать массив символв произвольной размерности: char a[]='Test';
Поменяй, малоли что!

Исправлено форматирование. -- ПК.
Re[2]: char* или char[]
От: adontz Грузия http://adontz.wordpress.com/
Дата: 02.01.04 11:54
Оценка:
Здравствуйте, kliff, Вы писали:

K>Неправильно и так и этак. По-любому нужно писать const.

K>
K>const char * s = "Test";
K>const char s[] = "Test";
K>


С чего бы во втором случае const? Это же простое объявление массива. Просто для массивов с типо элемента char введен специфический синтаксис инициализации.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: char* или char[]
От: kliff Россия http://www.esignal.ru
Дата: 02.01.04 12:10
Оценка:
Здравствуйте, adontz, Вы писали:

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


K>>Неправильно и так и этак. По-любому нужно писать const.

K>>
K>>const char * s = "Test";
K>>const char s[] = "Test";
K>>


A>С чего бы во втором случае const? Это же простое объявление массива. Просто для массивов с типо элемента char введен специфический синтаксис инициализации.


ага.. сорри, прогнал
Re: char* или char[]
От: Vamp Россия  
Дата: 02.01.04 19:58
Оценка:
Чуть-чуть саморекламы
См. http://www.rsdn.ru/article/cpp/cstr.xml
Автор(ы): Сергей Аристов
Дата: 28.12.2003
Это первая часть, в которой обсуждаются «традиционные» строки в С. В С++ существуют более удобные механизмы для работы со строковыми данными, эти механизмы рассматриваются во второй части статьи. А зачем вообще обсуждать неудобные С-строки, если есть С++? К сожалению, совсем забыть о строках в стиле С нельзя по двум причинам:
1. существует большое библиотек (например, API операционных систем) работающих именно с С-строками
2. строковые классы в С++ все равно основаны на традиционных С-строках, и если мы хотим разобраться в том, как они работают, нам придется понимать их основы.
Да здравствует мыло душистое и веревка пушистая.
Re: char* или char[]
От: Ultra.cpp Ниоткуда ultra-cpp.narod.ru
Дата: 02.01.04 20:15
Оценка:
Здравствуйте, INsideR, Вы писали:

INR>Есть следующий код:


INR>char* s = "Test";

INR>s[2] = 'b';

INR>У Страуструпа сказано, что это не верно, потому что char * указывает на строку с константными символами, надо писать так:

INR>char a[] = "Test";

INR>У меня в программе есть пару мест с char*, надо ли их переделывать?

Ты гонишь =)))
char a[] = "Test";
значит тоже самое что
char a[5] = "Test";
Наша работа -- во тьме,
Мы делаем, что умеем,
Мы отдаем, что имеем,
Наша работа во тьме.
Сомнения стали страстью,
А страсть стала судьбой,
Все остальное -- искуство,
В безумии быть собой
Re[4]: char* или char[]
От: Аноним  
Дата: 03.01.04 15:46
Оценка: -1
K>ага.. сорри, прогнал

Ничего не прогнал. Это два товарища выше не совсем понимают разницу между массивами и указателями.
Re[5]: char* или char[]
От: adontz Грузия http://adontz.wordpress.com/
Дата: 03.01.04 15:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ничего не прогнал. Это два товарища выше не совсем понимают разницу между массивами и указателями.


И в чём принципиальная разница?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[6]: char* или char[]
От: Аноним  
Дата: 03.01.04 16:50
Оценка:
Если нужна "постоянная" строка, то как раз-таки лучше писать const char str[] = "abcdef";
На счет массивов и указателей:
В случае const char *a = "abc"; под саму строку будет выделено четыре байта плюс на стеке (в случае локальной переменой) компилятор зарезервирует четыре байта для указателя и поместит туда адрес этой строки. В случае с глобальной — аналогично (четыре байта для самой строки и четыре байта на глобальный указатель). Если же у тебя есть const char b[] = "abc"; то здесь будет зарезервировано только четыре байта под саму строку без какого-либо указателя. При обращении к "а" (например printf(a) будет использовано содержимое указателя "а" в то время как при обращении к "b" (printf(b)) будет использоваться какое-то постоянно значение (непосредственный адрес строки в памяти).

И массив можно помечать как const!

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

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


А>>Ничего не прогнал. Это два товарища выше не совсем понимают разницу между массивами и указателями.


A>И в чём принципиальная разница?
Re[7]: char* или char[]
От: kliff Россия http://www.esignal.ru
Дата: 03.01.04 17:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Если нужна "постоянная" строка, то как раз-таки лучше писать const char str[] = "abcdef";

А>На счет массивов и указателей:
А>В случае const char *a = "abc"; под саму строку будет выделено четыре байта плюс на стеке (в случае локальной переменой) компилятор зарезервирует четыре байта для указателя и поместит туда адрес этой строки. В случае с глобальной — аналогично (четыре байта для самой строки и четыре байта на глобальный указатель). Если же у тебя есть const char b[] = "abc"; то здесь будет зарезервировано только четыре байта под саму строку без какого-либо указателя. При обращении к "а" (например printf(a) будет использовано содержимое указателя "а" в то время как при обращении к "b" (printf(b)) будет использоваться какое-то постоянно значение (непосредственный адрес строки в памяти).

Мое понимание строк было нечетким. Теперь вроде все стало на свои места.

const char * sz = "TEXT";
выделяется память под указатель на строку находящуюся в отсеке RO (память на строку выделена на этапе компиляции, а под переменная в рантайме на стеке)

const char sz[] = "TEXT";
везде используется непосредственный адрес строки находящейся в RO (память выделена на этапе компиляции)

char * sz = "TEXT";
подозреваю. что зависит от компилятора.. Помнится 6.0 такую строку размещал в отсеке WR, а 7.1 — RO. Соответственно 7.1 падает при попытке скопировать что-нить в такой буфер (хотя компилит без предупреждений).

char sz[] = "TEXT";
непосредственный адрес строки выделенной в рантайме на стеке и скопированный из отсека RO. Самый медленный, но в такой буфер можно писать.

Т.е. сомнительным является 3 случай. Следует избегать, но думаю переписывать куски уже рабочего кода не нужно (конечно если строка не используется как буфер).
Re[7]: char* или char[]
От: adontz Грузия http://adontz.wordpress.com/
Дата: 03.01.04 19:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Если нужна "постоянная" строка, то как раз-таки лучше писать const char str[] = "abcdef";


Если вообще нужно что-то постоянное, то лучше писать const вне зависимости от того что именно.

А>На счет массивов и указателей:


Угу.

А>В случае const char *a = "abc"; под саму строку будет выделено четыре байта плюс на стеке (в случае локальной переменой) компилятор зарезервирует четыре байта для указателя и поместит туда адрес этой строки.


Ну как-то так. Согласен.

А>Если же у тебя есть const char b[] = "abc"; то здесь будет зарезервировано только четыре байта под саму строку без какого-либо указателя.


Тоже верно.

А>При обращении к "а" (например printf(a) будет использовано содержимое указателя "а" в то время как при обращении к "b" (printf(b)) будет использоваться какое-то постоянно значение (непосредственный адрес строки в памяти).


И это праавильно. Но! В первоначальном вопросе была необходимость записи. Так что причём здесь const?
Да,
char * a = "text";

компилируется, ну а почему не должно? Ведь значение a может менятся во времени и если сейчас она указывает на "test" то потом на что-то другое.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[8]: char* или char[]
От: Vamp Россия  
Дата: 03.01.04 19:42
Оценка:
K>const char sz[] = "TEXT";
K>везде используется непосредственный адрес строки находящейся в RO (память выделена на этапе компиляции)
Мысль выражена не вполне четко . Уточню. Массив константных символов инициализируется строковым литералом TEST. Однако, насчет памяти (RO или RW) я бы не был так категоричен. В конце-концов, есть const_cast. Попытка изменить содержимое этого массива вызовет ошибку на этапе компиляции, вот единственное, что можно утверждать наверняка.

K>char * sz = "TEXT";

K>...Соответственно 7.1 падает при попытке скопировать что-нить в такой буфер (хотя компилит без предупреждений).
Наследство от С, в котором не было const. Я тоже не очень понимаю, почему не выдать хотя бы предупреждение.

K>char sz[] = "TEXT";

K>непосредственный адрес строки выделенной в рантайме на стеке и скопированный из отсека RO. Самый медленный, но в такой буфер можно писать.
По скорости не зависит от самого первого варианта.
Да здравствует мыло душистое и веревка пушистая.
Re[8]: char* или char[]
От: Vamp Россия  
Дата: 03.01.04 19:50
Оценка:
A>Да,
A>
A>char * a = "text";
A>

A>компилируется, ну а почему не должно? Ведь значение a может менятся во времени и если сейчас она указывает на "test" то потом на что-то другое.
Я считаю, уместно было бы предупреждение. Делов том, что тип "hello" — const char*. Тип a — char*. Попробуй провернуть такой фокус:
int i;
const int* cpi=&i;
int* ncpi=&i;
ncpi=cpi; //error: a value of type "const int *" cannot be assigned to
          //an entity of type "int *"


А со строковыми литералами именно это и получается.
Да здравствует мыло душистое и веревка пушистая.
Re[9]: char* или char[]
От: adontz Грузия http://adontz.wordpress.com/
Дата: 03.01.04 19:59
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Я считаю, уместно было бы предупреждение. Делов том, что тип "hello" — const char*. Тип a — char*. Попробуй провернуть такой фокус:

V>
V>int i;
V>const int* cpi=&i;
V>int* ncpi=&i;
V>ncpi=cpi; //error: a value of type "const int *" cannot be assigned to
V>          //an entity of type "int *"
V>

V>А со строковыми литералами именно это и получается.

А кто сказал что у "text" есть тип? Это у переменной есть тип. Это у "text" d контексте использования есть тип, а без контекста и типа нет.
void f(char * str)
 {
  str[0] = '_';
 }

void cf(const char * str)
 {
 }

f("text");
cf("text");


Хотя конечно предупреждение было бы и уместно.
A journey of a thousand miles must begin with a single step © Lau Tsu
char* или char[]
От: Павел Кузнецов  
Дата: 03.01.04 20:36
Оценка: 10 (5) +1
#Имя: FAQ.cpp.charptrorchararr
Здравствуйте, kliff, Вы писали:

const char * sz = "TEXT";
K>выделяется память под указатель на строку находящуюся в отсеке RO (память на строку выделена на этапе компиляции, а под переменная в рантайме на стеке)

Около того. Литерал "TEXT" может быть размещен в read-only памяти, но не обязательно. Существенным является то, что отдельно существует литерал "TEXT" (массив пяти const символов), и отдельно — указатель sz на первый элемент этого массива.

const char sz[] = "TEXT";
K>везде используется непосредственный адрес строки находящейся в RO (память выделена на этапе компиляции)

Формально существует литерал "TEXT", под который выделена память, плюс память под содержимое массива sz, в который скопированы символы литерала "TEXT". На практике некоторые компиляторы, естественно, могут использовать одну и ту же память как для литерала, так и для массива sz.

char * sz = "TEXT";
K>подозреваю. что зависит от компилятора.. Помнится 6.0 такую строку размещал в отсеке WR, а 7.1 — RO. Соответственно 7.1 падает при попытке скопировать что-нить в такой буфер (хотя компилит без предупреждений).

Размещение строковых литералов в read-only или read-write памяти в любом случае зависит от компилятора и его настроек и не зависит от того, какие указатели инициализируются данными литералами.

char sz[] = "TEXT";
K>непосредственный адрес строки выделенной в рантайме на стеке и скопированный из отсека RO. Самый медленный, но в такой буфер можно писать.

Формально это эквивалентно const char sz[] = "TEXT" за исключением того, что содержимое массива можно модифицировать. Однако, действительно, практически отсутствие const означает то, что компилятор вынужден копировать содержимое литерала в массив и не будет использовать одну и ту же память для литерала и массива sz.

K>Т.е. сомнительным является 3 случай. Следует избегать, но думаю переписывать куски уже рабочего кода не нужно (конечно если строка не используется как буфер).


Вывод верен.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[8]: char* или char[]
От: Павел Кузнецов  
Дата: 03.01.04 20:42
Оценка: +1
Здравствуйте, adontz, Вы писали:

A>причём здесь const?

A>Да,
A>
A>char * a = "text";
A>

A>компилируется, ну а почему не должно?

Если бы не было специального правила, введенного для совместимости со старым кодом, и явно разрешающего преобразование строковых литералов к char*, исходя из общих правил языка это не должно было бы компилироваться, т.к. строковые литералы имеют тип const char [...].

A> Ведь значение a может менятся во времени и если сейчас она указывает на "test" то потом на что-то другое.


Может ли меняться a к делу отношения не имеет, так как const перед char относился бы к данным, на которые указывает a, а не к самой переменной a. Т.е. означал бы, что, пользуясь переменной a нельзя изменять данные, на которые она указывает, но изменить a, так чтобы она указывала на другие данные вполне можно:
const char* a = "text";
a = "another text"; // ok
a[2] = 'b';         // error
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[10]: char* или char[]
От: Павел Кузнецов  
Дата: 03.01.04 20:57
Оценка: 20 (2)
Здравствуйте, adontz, Вы писали:

A>А кто сказал что у "text" есть тип? Это у переменной есть тип. Это у "text" d контексте использования есть тип, а без контекста и типа нет.


Тип есть у любого выражения. Например:
1;         // int
1l;        // long
1u;        // unsigned int
0.5;       // double
0.5f;      // float
'a';       // char
'ab';      // char
L'a';      // wchar_t
L'ab';     // wchar_t
1 + 2;     // int
1 + 'a';   // int
'a' + 'b'; // int

Строковые литералы без префикса L имеют тип const char [...], с префиксом L — const wchar_t [...]. В некоторых контекстах производится неявное преобразование к указателю:
"a";       // const char [2]
"ab";      // const char [3]
L"a";      // const wchar_t [2]
L"ab";     // const wchar_t [3]
"a" + 1;   // const char*
"ab" + 1;  // const char*
L"a" + 1;  // const wchar_t*
L"ab" + 1; // const wchar_t*
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.