Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> массив, объяснение 
:(
    Опции темы
observateur
Дата 11.9.2006, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 176
Регистрация: 10.6.2006

Репутация: нет
Всего: нет



Обьясните мне пожалоста тэорию массив типа char . Если  определяю массив типа char допостим:
char cp[]=”hello”;
я пишу : cout<<cp<<endl;     у меня выходит hello . если слово hello определен по ячейкам массива и если “cp” это указател на первую элемент массива тогда на каком основе “cp” выводит слово hello. (извините за мой русский язык).

Еще один вопрос что такое  символьные массивы-литералы ?
И еще один вопрос определение char cp[]=”hello”; является константным?

PM MAIL   Вверх
Prehistorik
Дата 11.9.2006, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 146
Регистрация: 30.5.2006
Где: СПб

Репутация: 1
Всего: 3



На том основании, что когда ты в коде указал "hello" то это на самом деле указатель на некую область в памяти, где лежат 5букв и потом символ с кодом ноль.
--------------------
Есть только один бог - Ассемблер, и С - пророк его. 
PM MAIL   Вверх
albertn
Дата 11.9.2006, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 368
Регистрация: 17.7.2006
Где: г. Ставрополь

Репутация: нет
Всего: 34



Я бы сказал конкретней, что char cp[]=”hello”; выделяет в некотором участке памяти место под хранение 6 символов, среди которых 5 относится к слову, и шестой - символ с нулевым кодом.
Вывод осуществляется до первого вхождения нулевого символа. Если по-какой либо причине в нужном месте его не окажется, то выводиться будет еще куча всякой белиберды.
символьные массивы - массивы символов (char*)
литерал - символ (char)
char cp[]=”hello”; это определение массива с инициализацией (не константа).
PS. RTFM!
PM WWW ICQ   Вверх
Sceptik
Дата 11.9.2006, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 29.8.2006
Где: Екатеринбург

Репутация: нет
Всего: нет



albertn, Не кричал бы ртфм то..).. char cp[] является константынм указателем.
PM MAIL ICQ   Вверх
albertn
Дата 11.9.2006, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 368
Регистрация: 17.7.2006
Где: г. Ставрополь

Репутация: нет
Всего: 34



Цитата(Sceptik @ 11.9.2006,  10:45)
albertn, Не кричал бы ртфм то..).. char cp[] является константынм указателем.

http://www.citforum.ru/programming/cpp_march/cpp_051.shtml
Есть еще вопросы?
PM WWW ICQ   Вверх
Sceptik
Дата 11.9.2006, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 29.8.2006
Где: Екатеринбург

Репутация: нет
Всего: нет



albertn, Пардон. Согласен ошибся.
PM MAIL ICQ   Вверх
Oleg_Ci
Дата 11.9.2006, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Friend
**


Профиль
Группа: Участник
Сообщений: 485
Регистрация: 28.5.2006
Где: Новосиб.обл.

Репутация: 3
Всего: 30



Цитата(observateur @  11.9.2006,  13:46 Найти цитируемый пост)
я пишу : cout<<cp<<endl;     у меня выходит hello . если слово hello определен по ячейкам массива и если “cp” это указател на первую элемент массива тогда на каком основе “cp” выводит слово hello.
Попробую объяснить:
cout<<  - здесь объект класса (cout) и перегруженный оператор <<(operator<<(char или char*)), так-вот этот "оператор вставки" может принимать в качестве пораметра и указатели типа char и выводить на консоль не адрес, а сому строку.
Цитата
Не забудьте, что в С++ строка представляется указателем на её местонахождение. Указатель может принимать форму имени массива типа char или явного указателя на тип char или строки в ковычках. Поэтому все следующие выражения отображают строки:
Код

char name[20] = "asdf";
char * pn = "asdf gg";

cout << "Hello";
cout << name;
cout << pn;


Цитата(observateur @  11.9.2006,  13:46 Найти цитируемый пост)
Обьясните мне пожалоста тэорию массив типа char . Если  определяю массив типа char допостим:char cp[]=”hello”;
Глава из Б. Керниган, Д. Ритчи  Язык программирования Си
Код

5.3 Указатели и массивы

В Си существует связь между указателями и массивами, и связь эта настолько
 тесная, что эти средства лучше рассматривать вместе. Любой доступ к элементу
 массива, осуществляемый операцией индексирования, может быть выполнен с
 помощью указателя. Вариант с указателями в общем случае работает быстрее,
 но разобраться в нем, особенно непосвященному, довольно трудно. 

Объявление
int a[10];

Определяет массив a размера 10, т. е. блок из 10 последовательных объектов с
 именами a[0], a[1], ..., a[9]. 
 

Запись a[i] отсылает нас к i-му элементу массива. Если pa есть указатель на int, 
т. е. объявлен как
int *pa;

то в результате присваивания 
pa = &a[0];

pa будет указывать на нулевой элемент a, иначе говоря, pa будет содержать 
адрес элемента a[0]. 

Теперь присваивание 
x = *pa;

будет копировать содержимое a[0] в x. 

Если pa указывает на некоторый элемент массива, то pa+1 по определению 
указывает на следующий элемент, pa+i - на i-й элемент после pa, a pa-i - на i-
й элемент перед pa. Таким образом, если pa указывает на a[0], то 
*(pa+1)

есть содержимое a[1], a+i - адрес a[i], a *(pa+i) - содержимое a[i]. 
 

Сделанные замечания верны безотносительно к типу и размеру элементов 
массива a. Смысл слов "добавить 1 к указателю", как и смысл любой 
арифметики с указателями, состоит в том, чтобы pa+1 указывал на следующий 
объект, a pa+i - на i-й после pa. 

Между индексированием и арифметикой с указателями существует очень тесная 
связь. По определению значение переменной или выражения типа массив есть 
адрес нулевого элемента массива. После присваивания 
pa = &a[0];

ра и a имеют одно и то же значение. Поскольку имя массива является 
синонимом расположения его начального элемента, присваивание pa=&a[0] 
можно также записать в следующем виде: 
pa = a;

Еще более удивительно (по крайней мере на первый взгляд) то, что a[i] можно 
записать как *(a+i). Вычисляя a[i], Си сразу преобразует его в *(a+i); 
указанные две формы записи эквивалентны. Из этого следует, что полученные в
 результате применения оператора & записи &a[i] и a+i также будут 
эквивалентными, т. е. и в том и в другом случае это адрес i-го элемента после 
a. С другой стороны, если pa - указатель, то его можно использовать с 
индексом, т. е. запись pa[i] эквивалентна записи *(pa+i). Короче говоря, 
элемент массива можно изображать как в виде указателя со смещением, так и в 
виде имени массива с индексом. 

Между именем массива и указателем, выступающим в роли имени массива, 
существует одно различие. Указатель - это переменная, поэтому можно 
написать pa=a или pa++. Но имя массива не является переменной, и записи 
вроде a=pa или a++ не допускаются. 

Если имя массива передается функции, то последняя получает в качестве 
аргумента адрес его начального элемента. Внутри вызываемой функции этот 
аргумент является локальной переменной, содержащей адрес. Мы можем 
воспользоваться отмеченным фактом и написать еще одну версию функции 
strlen, вычисляющей длину строки. 
/* strlen: возвращает длину строки */
int strlen(char *s)
{
    int n;
    for (n = 0; *s != '\0'; s++)
        n++;
    return n;
}

Так как переменная s - указатель, к ней применима операция ++; s++ не 
оказывает никакого влияния на строку символов функции, которая обратилась 
к strlen. Просто увеличивается на 1 некоторая копия указателя, находящаяся в 
личном пользовании функции strlen. Это значит, что все вызовы, такие как: 
strlen("3дравствуй, мир"); /* строковая константа */
strlen(array);             /* char array[100]; */
strlen(ptr);               /* char *ptr; */

правомерны. 

Формальные параметры
char s[];

и
char *s;

в определении функции эквивалентны. Мы отдаем предпочтение последнему 
варианту, поскольку он более явно сообщает, что s есть указатель. Если 
функции в качестве аргумента передается имя массива, то она может 
рассматривать его так, как ей удобно - либо как имя массива, либо как 
указатель, и поступать с ним соответственно. Она может даже использовать оба
 вида записи, если это покажется уместным и понятным. 

Функции можно передать часть массива, для этого аргумент должен указывать 
на начало подмассива. Например, если a - массив, то в записях
f(&a[2])

или
f(a+2)

функции f передается адрес подмассива, начинающегося с элемента a[2]. 
Внутри функции f описание параметров может выглядеть как
f(int arr[]) {...}

или
f(int *arr) {...}

Следовательно, для f тот факт, что параметр указывает на часть массива, а не 
на весь массив, не имеет значения. 

Если есть уверенность, что элементы массива существуют, то возможно 
индексирование и в "обратную" сторону по отношению к нулевому элементу; 
выражения p[-1], p[-2] и т.д. не противоречат синтаксису языка и обращаются 
к элементам, стоящим непосредственно перед p[0]. Разумеется, нельзя 
"выходить" за границы массива и тем самым обращаться к несуществующим 
объектам.
И ещё:
Код

5.5 Символьные указатели функции

Строковая константа, написанная в виде 
"Я строка"

есть массив символов. Во внутреннем представлении этот массив заканчивается 
нулевым символом '\0', по которому программа может найти конец строки. 
Число занятых ячеек памяти на одну больше, чем количество символов, 
помещенных между двойными кавычками. 

Чаще всего строковые константы используются в качестве аргументов функций,
 как, например, в 
printf("здравствуй, мир\n");

Когда такая символьная строка появляется в программе, доступ к ней 
осуществляется через символьный указатель; printf получает указатель на 
начало массива символов. Точнее, доступ к строковой константе 
осуществляется через указатель на ее первый элемент. 

Строковые константы нужны не только в качестве аргументов функций. Если, 
например, переменную pmessage объявить как 
char *pmessage;

то присваивание
pmessage = "now is the time";

поместит в нее указатель на символьный массив, при этом сама строка не 
копируется, копируется лишь указатель на нее. Операции для работы со 
строкой как с единым целым в Си не предусмотрены. 

Существует важное различие между следующими определениями: 
char amessage[] = "now is the time"; /* массив */
char *pmessage = "now is the time";  /* указатель */

amessage - это массив, имеющий такой объем, что в нем как раз помещается 
указанная последовательность символов и '\0'. Отдельные символы внутри 
массива могут изменяться, но amessage всегда указывает на одно и то же место 
памяти. В противоположность ему pmessage есть указатель, 
инициализированный так, чтобы указывать на строковую константу. А значение 
указателя можно изменить, и тогда последний будет указывать на что-либо 
другое. Кроме того, результат будет неопределен, если вы попытаетесь 
изменить содержимое константы. 
 

Дополнительные моменты, связанные с указателями и массивами, 
проиллюстрируем на несколько видоизмененных вариантах двух полезных 
программ, взятых нами из стандартной библиотеки. Первая из них, функция 
strcpy (s, t), копирует строку t в строку s. Хотелось бы написать прямо s = t, 
но такой оператор копирует указатель, а не символы. Чтобы копировать 
символы, нам нужно организовать цикл. Первый вариант strcpy, с 
использованием массива, имеет следующий вид: 
/* strcpy: копирует t в s; вариант с индексируемым массивом*/
void strcpy(char *s, char *t)
{
    int i;
    i = 0;
    while ((s[i] = t[i]) != '\0')
        i++;
}


Для сравнения приведем версию strcpy с указателями: 


/* strcpy: копирует t в s: версия 1 (с указателями) */
void strcpy(char *s, char *t)
{
    while ((*s = *t) != '\0') {
        s++;
        t++;
    }
}

Поскольку передаются лишь копии значений аргументов, strcpy может свободно 
пользоваться параметрами s и t как своими локальными переменными. Они 
должным образом инициализированы указателями, которые продвигаются 
каждый раз на следующий символ в каждом из массивов до тех пор, пока в 
копируемой строке t не встретится '\0'. 

На практике strcpy так не пишут. Опытный программист предпочтет более 
короткую запись: 
/* strcpy: копирует t в s; версия 2 (с указателями) */
void strcpy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0')
        ;
}

PM MAIL   Вверх
albertn
Дата 11.9.2006, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 368
Регистрация: 17.7.2006
Где: г. Ставрополь

Репутация: нет
Всего: 34



Цитата(Олег4 @  11.9.2006,  16:32 Найти цитируемый пост)
cout<<  - здесь объект класса (cout) и перегруженный оператор <<(operator<<(char или char*)), так-вот этот "оператор вставки" может принимать в качестве пораметра и указатели типа char и выводить на консоль не адрес, а сому строку.

ИМХО ему еще рано касаться перегрузки. Ему бы доки какие-нить почитать, а еще лучше книжку. А знания полученные методом научного тыка имхо не всегда объективны.
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0663 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.