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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 8, средняя оценка - 4.63
WLF
0 / 0 / 0
Регистрация: 06.12.2013
Сообщений: 24
#1

Обязательно ли объявлять переменную для хранения адреса переменной как указатель? - C++

09.05.2014, 09:12. Просмотров 1248. Ответов 38
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Указатели
#include <iostream>
 
using namespace std;
 
int Variable;
int *pVariable;
// int pVariable;
int main()
{
    setlocale(LC_ALL, "rus");
 
    Variable = 777;
    pVariable = &Variable;
 
    cout << "Переменная Variable\t = " << Variable << endl;
    cout << "Адрес Variable\t\t = " << &Variable << endl;
    cout << "Значение по этому адресу = " << *pVariable << endl;
    // cout << "Значение по этому адресу = " << pVariable << endl;
return 0;
}
Скажите, почему, если я объявляю переменную pVariable просто как int, а не как указатель (закомментированые строки), то компилятор ругается на типы? Разве, чтобы хранить в переменной какой-то адрес надо обязательно объявлять её как указатель?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.05.2014, 09:12
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Обязательно ли объявлять переменную для хранения адреса переменной как указатель? (C++):

Как правильно объявлять struct переменную? - C++
Как правильно объявлять? str one или struct str one; #include &lt;iostream&gt; using namespace std; struct str { int a; int b; ...

Используя указатель на переменную типа string, удалить последний символ этой переменной - C++
есть указатель на переменную string,нужно удалить последний символ этой переменной работая с указателем.Как это осуществить?Заранее...

Описать класс,содержащий переменную для хранения текстовой строки. - C++
Описать класс,содержащий переменную для хранения текстовой строки.Вне класса притв функцию,которая определит какое слово встречается в...

Где объявлять переменную: перед циклом, или внутри класса - C++
Подскажите, где правильно объявить переменную. Если объявить внутри цикла, то сузится область ее видимости, но она будет объявляться...

Не обязательно разыменовывать указатель на функцию при вызове? - C++
Здравствуйте. Вот такой вопрос. void estimate(int lines, double (*pf) (int)); //прототип // ... void estimate(int lines, double...

Как использовать указатель на переменную во входящем параметре функции? - C++
Нашел код для решение гиперболического уравнение с помощью разностных схем. Возникли некоторые вопросы. Вот сам код: double...

38
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.05.2014, 10:42 #16
WLF, адрес это не просто число. Адреса например нельзя складывать в отличии от чисел. Т.к. результат этого действия не несет смысла. В некоторых случаях адрес можно преобразовывать в целое число и обратно, но это не делается автоматически.
Как будет выводится на экран то или иное значение через operator << зависит от типа, который ему будет передан. Целые по умолчанию выводятся в десятичном формате, а адреса в шестнадцатиричном. Задавая манипуляторы типа std::hex std::dec можно менять это поведение.
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
09.05.2014, 10:44 #17
Указатель есть целое специального вида, предназначенное только для хранения номера байта, с которого начинается некоторое данное, или функция. Адрес есть значение номера байта, с которого начинается некоторое данное, или функция. Значение указателя - это адрес, но адрес и указатель - разные сущности, соотносимые также, как число и переменная числового типа: адрес - значение указателя, указатель - данное, хранящее адрес.
1
WLF
0 / 0 / 0
Регистрация: 06.12.2013
Сообщений: 24
09.05.2014, 11:08  [ТС] #18
Да так-то понятно, что указатель это тип данных для адреса. Просто меня заинтересовало физика процесса можно ли обойтись без звездочек...

Цитата Сообщение от Tulosba Посмотреть сообщение
Задавая манипуляторы типа std::hex std::dec можно менять это поведение.
cout << "Адрес Variable\t\t = " << dec << &Variable << endl;
не работает. namespace задан (листинг в первом сообщении).

И пример отсюда не компилится.
|2|fatal error: iostream: No such file or directory|


Добавлено через 12 минут
Пример скомпилился, dec/hex работает, а у меня почему-то нет...
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
09.05.2014, 11:28 #19
Цитата Сообщение от WLF Посмотреть сообщение
можно ли обойтись без звездочек
Нельзя, даже
C++
1
2
3
4
int x;
size_t p;
p=(size_t)(&x);
*((int*)p)=2;
требует вместо одной двух звёздочек при каждом разыменовании: одна для приведения к указателю, так как разыменовать можно только его, вторая для разыменования. А кроме как разыменованием ни как обратиться целиком к данному по его адресу нельзя. Функцию можно вызвать по адресу, не разыменуя, но и тогда одна звёздочка нужна будет при каждом вызове для приведения. Ещё можно по указателю и только по указателю получить доступ к члену, используя адрес всего объекта/структуры, но
C++
1
2
3
4
5
6
7
8
9
struct s
{
 int a;
 int b;
};
size_t p;
s d;
p=(size_t)(&x);
((s*)p)->b=2;
требует звёздочки для приведения при каждом доступе. Компилятор интерпретирует в качестве адресов только значения указателей и пока ты синтаксически не оформил указатель, использовать адрес не получится.
1
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
09.05.2014, 13:23 #20
Цитата Сообщение от WLF Посмотреть сообщение
cout << "Адрес Variable\t\t = " << dec << &Variable << endl;
Для вывода адреса указателя манипуляторы не действуют. Я не совсем корректно выразился в предыдущем сообщении. Но если нужно вывести адрес в десятичном представлении, можно рассмотреть такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cstdint>
 
int main() {
    
    int i;
    int *p = &i;
    
    std::cout << std::dec << p << std::endl; // Указатель выводится всегда в hex
    std::cout << std::hex << p << std::endl; // т.к. манипулятор действует только на целые типы
 
    // Если преобразовать указатель в целое, то манипуляторы будут действовать
    // Значение (адрес) остаются прежними
    std::cout << std::dec << reinterpret_cast<uintptr_t>(p) << std::endl;
    std::cout << std::showbase << std::hex << reinterpret_cast<uintptr_t>(p) << std::endl;
    
    return 0;
}
http://ideone.com/CCe6XE

Кстати, если нужно преобразовывать значение указателя в целое и обратно, правильным будет именно использование типов uintptr_t/intptr_t, а не просто int, у которого может не хватить разрядности.
Integer types capable of holding object pointers

The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to a pointer to void, and the result will compare equal to the original pointer: intptr_t

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to a pointer to void, and the result will compare equal to the original pointer: uintptr_t
отсюда

Цитата Сообщение от taras atavin Посмотреть сообщение
p=(size_t)(&x);
типа size_t может не хватить для представления адреса. См. первый комментарий к ответу тут.
1
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2014, 08:18 #21
Цитата Сообщение от Tulosba Посмотреть сообщение
типа size_t может не хватить для представления адреса.
Это где же я такое написал то? Изначально предлагался long int, вот его и может не хватить, если вдруг адрес будет 128-ми битным, а long int останется 64-х битным. И даже long long int - не выход, если адрес вдруг станет 256-ти битным. Виртуальные адреса могут иметь любую разрядность, ни как не связанную с объёмом физической памяти и даже превосходить двоичный логарифм реально доступного объёма памяти на множитель в виде любой степени двойки и единственный не указательный тип, разрядность которого гарантировано достаточна для представления адреса - это как раз size_t, так как это платформенно-зависимый тип, разрядность которого растёт вместе с разрядностью адреса.

Добавлено через 8 минут
Что касается вопроса в названии темы, переменную для использования в качестве указателя можно декларировать не указательного типа. Но при всяком её использовании понадобится приведение типа: при присваивании ей значения приведение указателя к её типу, а при обращении по адресу явное приведение самой переменной к указателю. Это дополнительные синтаксические сложности, вызванные тем, что единственная сущность, для которой разрешён синтаксис, за которым скрывается необходимая для обращения по адресу косвенная адресация, - это указатель. Всё остальное адрес может только хранить, да и то ровно один тип гарантирует, что в него влезет весь адрес - size_t, остальные могут оказаться пригодными лишь для хранения части адреса, например, приращения в 256-ти байтном параграфе (char и uint8_t при адресации по смещению каждого байта).

Добавлено через 1 минуту
Тем не менее, часть адреса можно хранить в переменной любого типа, вопрос лишь в том, какую именно часть адреса можно хранить в переменной каждого типа. Можно даже поизвращаться и хранить весь адрес в строке, количество символов которой уравнять с sizeof(size_t).

Добавлено через 6 минут

Limit of size_t:

{SIZE_MAX}
65535
Это в 16-ти битных версиях. У меня 32-х битный компилятор, под ним 4294967296.
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
10.05.2014, 10:28 #22
taras atavin, если сразу не понятно, вот еще пара ссылок:
http://stackoverflow.com/questions/1...ze-in-practice
http://stackoverflow.com/questions/1464174/size-t-vs-intptr-t
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2014, 11:27 #23
Эйси.
size_t is pointer size in practice
. size_t есть тип, чья разрядность практически равна разрядности указателя. Цитату в студию, где я утверждаю обратное.
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
10.05.2014, 11:38 #24
Цитата Сообщение от taras atavin Посмотреть сообщение
ровно один тип гарантирует, что в него влезет весь адрес - size_t
Это не так. size_t тип в первую очередь для хранения размера, а не адреса. В некоторых случаях разрядности size_t может не хватить для представления адреса. См. ещё раз ссылки, которые я давал.

Не по теме:

Цитата Сообщение от taras atavin Посмотреть сообщение
разрядность практически равна разрядности указателя
"У меня практически нет недвижимости за рубежом" © Бывший депутат ГД РФ Пехтин В.А.

0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2014, 11:46 #25
Цитата Сообщение от Tulosba Посмотреть сообщение
size_t тип в первую очередь для хранения размера, а не адреса.
Где я утверждал обратное?
Цитата Сообщение от Tulosba Посмотреть сообщение
Это не так.
Разве? Чем, кроме возможности разыменования, различаются типы предназначенные для хранения размера памяти и адреса в этой памяти? Ведь ни кто не гарантирует, что size_t будет применён для хранения размера именно области памяти, причём, много меньшей, чем вся память, он обязан гарантировать свою достаточность для представления размера любой области памяти вне зависимости от возможности существования иных областей, не пересекающихся с данной.
0
newbie666
Заблокирован
10.05.2014, 11:49 #26
Цитата Сообщение от taras atavin Посмотреть сообщение
Ведь ни кто не гарантирует, что size_t будет применён для хранения размера именно области памяти
на самом деле в виртуальною память процесса можно достучаться как годно, просто через указатель - проще
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2014, 11:55 #27
Цитата Сообщение от newbie666 Посмотреть сообщение
на самом деле в виртуальною память процесса можно достучаться как годно, просто через указатель - проще
И как же ещё?
C++
1
((int*)p)=2;
тоже использует указатель, так как значение оператора приведения к указателю есть указатель. Только этот указатель - не переменная, а временное данное, существующее лишь номинально, так как приведение происходит без фактического преобразования, и только во время самой операции доступа по адресу, в этом указателе хранящемуся. Но это указатель, синтаксис языка запрещает без помощи указателя обращаться по адресу, хранимому не в самой инструкции, а в данном. Больше того, можно даже использовать указатель, являющийся значением выражения, то есть результатом вычисления, тогда для него вообще не надо заводить отдельную переменную.
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
10.05.2014, 11:58 #28
taras atavin, Вы ссылки смотрели, которые я приводил?
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2014, 12:04 #29
Например,
C++
1
2
3
int *p=new int [2048];
*(p+264)=22;
delete [] p;
. Указателей здесь два, один p, а другой равен p+264*sizeof(int), причём, умножение подразумевается благодаря типизации p. А переменная то указательного типа одна - указатель p, целиком же фактический адрес элемента массива вообще не хранится в какой либо переменной.

Добавлено через 1 минуту
Цитата Сообщение от Tulosba Посмотреть сообщение
Вы ссылки смотрели, которые я приводил?
А давайте без тумана и килострок текста? Конкретный пример прямо сюда, чтоб не продираться через всё остальное.
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
10.05.2014, 12:23 #30
Цитата Сообщение от taras atavin Посмотреть сообщение
А давайте без тумана и килострок текста?
Там всё написано буквально в самых первых ответах:
AFAIK, on AS/400 pointers are 128-bit, but size_t is defined to be 32-bit.
отсюда
Hark back to the days of segmented 16-bit architectures for example: an array might be limited to a single segment (so a 16-bit size_t would do) BUT you could have multiple segments (so a 32-bit intptr_t type would be needed to pick the segment as well as the offset within it). I know these things sound weird in these days of uniformly addressable unsegmented architectures, but the standard MUST cater for a wider variety than "what's normal in 2009", you know!-)
отсюда

Перевод нужен или снова будете игнорировать факты и напускать туман?
0
10.05.2014, 12:23
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.05.2014, 12:23
Привет! Вот еще темы с ответами:

Можно ли как-то словить номер элемента используя указатель, а не переменную - C++
void Print(int *arr, const int *size) { for (int *p = arr, n=0; p &lt; arr + *size; p++) cout &lt;&lt; &quot; - &quot; &lt;&lt; *p &lt;&lt; endl; cout &lt;&lt;...

Реализуйте класс для хранения ФИО и номера телефона человека, класс для хранения даты рождения человека, а также класс для хранения ФИО и почтового ад - C++
Реализуйте класс для хранения ФИО и номера телефона человека, класс для хранения даты рождения человека, а также класс для хранения ФИО и...

Как вывести на экран переменную из функции, которой присваиваеться значение через указатель? - C++
Только начал изучать С++. И не могу понять, как вывести на экран переменную pdLocalVar из функции child(), которой присваивается значение в...

Как объявлять указатель на массив указателей? - C (СИ)
Народ, поясните как объявлять указатель на массив указателей и как отправлять его как параметр в функцию


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru