Форум программистов, компьютерный форум CyberForum.ru

Несколько вопросов по указателям. - C++

Восстановить пароль Регистрация
 
fermerius
0 / 0 / 0
Регистрация: 24.10.2010
Сообщений: 19
25.02.2011, 15:17     Несколько вопросов по указателям. #1
Добрый день. Не получается до конца разобраться с указателями, потому есть несколько вопросов. Кому несложно, помогите, пожалуйста.

1. Указатель, это переменная которая хранит адрес в памяти, так ? В таком случае, почему указатель типа char *ptr = some_string после оператора cout<<ptr показывает не адрес, а саму строку ?

2. Можно ли как-то изменить строку целиком через *указатель ? Не по символам, а сразу передать другое значение ?

3.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string.h>
#include <conio.h>
#include <iostream.h>
 
void nills(char *str)
{
    
   while(*str){
    *str='0';
    str++;
}
    
     }
 
int main()
{
  char a[7]="fsdfs";
  nills(a);
  nills("fsd");
  
  getche();
    }
Почему при вызове функции nills и передаче параметра как переменную, программа работает. А если в функциюю сразу передавать строку nills("fsd"); то программа зависает ?

4. В этой же программе. Параметр str помечен как указатель - void nills(char *str). Это значит что внутри функции, обращаясь к str, я работаю с указателем ?

Спасибо заранее.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.02.2011, 15:17     Несколько вопросов по указателям.
Посмотрите здесь:

Несколько вопросов по извучению C++ C++
несколько вопросов. WinApi C++
Несколько вопросов C++
Несколько вопросов по строкам в С C++
C++ Несколько вопросов
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
25.02.2011, 15:54     Несколько вопросов по указателям. #2
1. Да, указатель - это переменная, способная хранить адрес другой переменной. Однако имя массива можно считать адресом его первой ячейки. Так что, по сути, передавая в operator<< str (где str - char str[] = "Hello, World!, вы передаёте адрес начала строки. Так же вы делаете, передавая ptr (ptr - char *ptr = str, потому компилятор трактует превую и вторую запись одинаково.
2. Нет, так же, как этого нельзя сделать с самой строкой, по одной простой причине - в Си и Си++ нет присваивания сырых строк.
3. Когда вы передаёте сразу строку "fsd" - она является константной. Следовательно, при попытке изменить константную строку происходит глобальный парадокс , чего не скажешь о переменной char *.
4. Да. Но, как я уже говорил, имя массива является адресом его первого элемента, т.е. работая с любым сырым массивом вы, по сути, работаете с указателем. Даже конструкция arr[3] разворачивается компилятором в *(arr + 3).
bigredcat
364 / 311 / 3
Регистрация: 24.02.2011
Сообщений: 1,512
Записей в блоге: 1
25.02.2011, 16:09     Несколько вопросов по указателям. #3
Цитата Сообщение от fermerius Посмотреть сообщение
1. Указатель, это переменная которая хранит адрес в памяти, так ? В таком случае, почему указатель типа char *ptr = some_string после оператора cout<<ptr показывает не адрес, а саму строку ?
Да, указатель, это переменная которая хранит адрес.
О перегрузке операторов знаете? Короче, стандартная библиотека так реализована, что для типа char* выполняется вывод строки, а не ее адреса.

Цитата Сообщение от fermerius Посмотреть сообщение
2. Можно ли как-то изменить строку целиком через *указатель ? Не по символам, а сразу передать другое значение ?
Думайте о строке, как о массиве символов (по сути одно или многобайтовых целых чисел), всегда имееющем в конце 0. И все станет понятно.

Цитата Сообщение от fermerius Посмотреть сообщение
3. Почему при вызове функции nills и передаче параметра как переменную, программа работает. А если в функциюю сразу передавать строку nills("fsd"); то программа зависает ?
nills("fsd") - здесь вы передаете константу "fsd", а затем пытаетесь выполнить запись в нее *str='0' и получаете исключение.

Цитата Сообщение от fermerius Посмотреть сообщение
4. В этой же программе. Параметр str помечен как указатель - void nills(char *str). Это значит что внутри функции, обращаясь к str, я работаю с указателем ?
Да. А здесь *str вы используете оператор разыменования (*) и получаете доступ к значению, хранимому по адресу указателя.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
25.02.2011, 16:23     Несколько вопросов по указателям. #4
По поводу первого хочу добавить - такая запись:
C++
1
cout<<"Hello";
трактуется компилятором как:
C++
1
cout<<str;//где str это указатель на строку "Hello"
Просто для удобства работы можно писать сразу нужную строку для вывода, но при компиляции компилятор запишет ее в защищенную область памяти (строка же константная), а объекту cout будет отправлен указатель на эту строку.

Чтобы был выведен сам указатель (т.е. адрес строки) нужно сделать так:
C++
1
cout<<(long)str;
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
25.02.2011, 16:33     Несколько вопросов по указателям. #5
Kastaneda, кстати говоря, интересно, static_cast< long >(ptr) не работает, говорит о недопустимом преобразовании. Зато сырое (long)ptr - запросто выводит адрес.

Добавлено через 52 секунды
Ага, понятно, зато reinterpret_cast работает)))
fermerius
0 / 0 / 0
Регистрация: 24.10.2010
Сообщений: 19
25.02.2011, 23:32  [ТС]     Несколько вопросов по указателям. #6
Спасибо всем огромное за ответы с объяснениями. И еще один вопрос по теме.

Отрывок из статьи про указатели.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
char *string_uppercase(char* string) 
 
{ 
   char *starting_address = string; // адрес string[0]; 
   while (*string) 
 
   { 
      if ((*string >= 'а') && (*string <= 'я')) *string = *string - 'a' + 'A'; 
      string++; 
   } 
   return(starting_address); 
} 
 
//Эта функция сохраняет и возвращает начальный адрес строки, 
//который позволяет вашим программам использовать функцию следующим образом: 
 
cout << String_uppercase("Привет, мир!") << endl;

1. Для чего стоит * перед именем функции ? Чтобы можно было ей возвратить значение целого массива символов ? Я правильно понимаю, что без * функции можно возвратить только один символ ?

2. В этой функции мы тоже (как и в примере ранее) передаем константную строку, но программа не ругается. В чем подвох ? Неужто в этом знаке " * " перед именем функции ?

3. И еще вопрос, что за махинации с указателем char *starting_address ? Я объясню как я понял, скажите если где-то пробел. Внутри функции мы объявляем еще один указатель char *starting_address, и он указывает туда же, куда указывает указатель *string (а он указывает на константкую строку). Далее производятся изменения с указателем на константную строку (ведь сама строка не может быть изменена). И вот тут дальше мне не понятно. Как можно изменять сам указатель если он лишь указывает ? И разве char *starting_address не изменится от этого ?

4. И еще один маленький ) Почему string++ а не *string++ ? Ведь именно *string показывает 1 символ, а string всю строку целиком ?



Прошу прощения за большой текст, в голове каша невероятная с этими указателями. Спасибо заранее.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.02.2011, 00:41     Несколько вопросов по указателям.
Еще ссылки по теме:

Несколько вопросов C++
Несколько вопросов к программистам. C++
C++ даны несколько задач по указателям

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

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
26.02.2011, 00:41     Несколько вопросов по указателям. #7
fermerius,
1. Точнее, чтобы функция могла возвратить указатель. И снова возвращаемся к тому, что имя массива - адрес его начала, а, значит, указатель, возвращённый функцией, может интерпретироваться как массив.
2. Вообще-то программа должна виснуть (и у меня виснет, не знаю, почему у вас отрабатывает нормально). И всё по той же причине - строка константная.
3. Буду объяснять, учитывая, что передана функции неконстантная строка. Вся фишка в том, что в строке 9 происходит модификация указателя string, а именно, происходит сдвиг на один элемент массива. Мы же хотим, чтобы функцию можно было использовать так, как сделано в строке 17, т.е. использовать её саму как строку (например, как в данном случае, выводить с помощью <<). А чтобы это сделать, функция должна возвращать указатель на начало строки. Поэтому мы в starting_address запоминаем это адрес, а затем сам string модифицируем. Т.о. перед завершением функции у нас будет string, который теперь указывает на конец строки (благодаря чему мы и перемещались по строке), а так же starting_address, который по-прежнему указывает на её начало и который мы и возвращаем в качестве результата.
4. Здесь нам надо работать с указателем, а не со значением. Мы и применяем инкремент к указателю, тем самым сдвигая его на одну ячейку типа char.
Yandex
Объявления
26.02.2011, 00:41     Несколько вопросов по указателям.
Ответ Создать тему
Опции темы

Текущее время: 09:41. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru