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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.73
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
#1

Оператор -> и спецификатор класса памяти extern - C++

08.01.2012, 02:40. Просмотров 1953. Ответов 16
Метки нет (Все метки)

Оператор ->
Исходя из того, что он вообще был добавлен в язык, можно сделать вывод, что такая *struct.elem запись уже где-то используется (не для доступа к элементу elem структуры struct), и оператор -> добавлен для того чтобы избежать путаницы (и используется такая struct->elem запись). Вопрос: где используется такая *struct.elem запись?

Cпецификатор класса памяти extern
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.01.2012, 02:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Оператор -> и спецификатор класса памяти extern (C++):

Спецификатор автоматического класса памяти, register - C++
Прочитал: Register. Ещё один спецификатор автоматического класса памяти. Применяется к объектам, по умолчанию располагаемым в локальной...

Как грамотно убрать класс с глобальной видимости, удалив оператор extern? - C++
Пусть есть такие файлы исходного кода: main.cpp: #include "classA.h" extern classA aObj; int main() {

Для шаблонного класса перегрузить оператор присваивания, copy-конструктор, объекты cin и cout, оператор * - C++
Помогите в следующем: Для класса шаблона следует перегрузить оператор присваивания, конструктор копирования, бинарный оператор суммы «*»,...

Спецификатор noexcept для класса "исключение" - C++
Доброго все дня! Стандартный класс std::exception имеет спецификатор noexcept для всех своих методов/операторов/конструкторов. Однако, он...

Реализовать оператор= для присваивания объекта класса-потомка объекту базового класса - C++
Есть два класса A и B, причем класс B является потомком A. Как реализовать следующее: obj_A = obj_B и obj_B = obj_A? Добавлено через 9...

Создать конструктор копий и оператор присваивания для класса компьютер и члена класса марка - C++
Создать конструктор копий и оператор присваивания для класса компьютер и члена класса марка. Всем огромное спасибо за помощь! |

16
Jupiter
Каратель
Эксперт С++
6560 / 3981 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.01.2012, 02:44 #2
например
Цитата Сообщение от Tamoren Посмотреть сообщение
Вопрос: где используется такая *struct.elem запись?
C
1
2
3
4
5
struct mystruct {
    int* elem;
} obj;
//...
*obj.elem = 100500;
0
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 03:05  [ТС] #3
То есть если у нас есть указатель *p на структуру obj, то для доступа к её елементу element нужно использовать p->element (и компилятор сам догадается, что p - указатель, и не нужно перед p ставить *)
Если у нас есть указатель int* elem в структуре obj, то чтобы присвоить значение 100500 переменной, на которую ссылается указатель elem структуры obj нужно использовать *obj.elem = 100500.
А что если у меня есть указатель *p на элемент element структуры obj? Как мне этому елементу присвоить значение 100500? Я бы тогда здесь использовал *obj.elem = 100500. А в предыдущем получается obj.*elem = 100500...
0
Jupiter
Каратель
Эксперт С++
6560 / 3981 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.01.2012, 04:19 #4
вот зачем все усложнять, есть аксиомы которым нужно следовать, если всё поддавать сомнению то и...

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdlib.h>
#include <stdio.h>
 
struct mystruct {
    int* elem;
} obj, *pobj;
 
int main(void)
{
   obj.elem = malloc(sizeof(int));
   *obj.elem = 100500;
   printf("%d\n", *obj.elem);
   pobj = &obj;
   *pobj->elem = 100501;
   printf("%d\n", *obj.elem);
   *(*pobj).elem = 100502;
   printf("%d\n", *obj.elem);
   free(pobj->elem);
   return 0;
}
http://liveworkspace.org/code/e902e62a068e976c02535ce62e385fcb
0
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 06:18  [ТС] #5
Что-то я вообще не понимаю что это:
Цитата Сообщение от Jupiter Посмотреть сообщение
C
1
*(*pobj).elem = 100502;
В плюсах это ведь также выглядит?

В общем вот структура:
C++
1
2
3
    struct struct_type {
        int a, *pa;
    } str, *pstr;
C++
1
2
3
4
5
6
7
8
9
10
11
    pstr = &str;
    str.pa = &str.a;
    pstr = &str;
    str.a = 1; //Через саму структуру
    cout << str.a << ", ";
    *str.pa = 2; //Через указатель на элемент
    cout << str.a << ", ";
    pstr->a = 3;//Через указатель на структуру
    cout << str.a << ", ";
    *pstr->pa = 4;//Через указатель на структуру, в которой содержится указатель на элемент
    cout << str.a << ", ";
Вроде работает правильно. Смысл понял. Дело было в более высоком приоритете "." или "->" (над "*").
0
alkagolik
Заблокирован
08.01.2012, 12:53 #6
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
 
struct str_type {
    int* el;
} obj, *pobj;
 
int main ( void )
{
    int x = 100500;
 
    obj.el = &x;
    pobj = &obj;
    printf("%i\n", *pobj->el );
 
    ++( *pobj->el );
    printf("%i\n", *pobj->el );
 
    ++x;
    printf("%i\n", *pobj->el );
    return 0;
}
http://liveworkspace.org/code/995898497eb08c14a1055fc659959671
на уровне процессора ( *pobj ).el == pobj->el. "->" просто удачное решение от создателей. Чтим, помним и уважаем.

Добавлено через 5 минут
C
1
2
    printf("%i\n", *(*pobj).el );
    printf("%i\n", *pobj->el );
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
0x8048408   mov    eax,ds:0x804a01c
0x804840d   mov    eax,DWORD PTR [eax]
0x804840f   mov    edx,DWORD PTR [eax]
0x8048411   mov    eax,0x8048520
0x8048416   mov    DWORD PTR [esp+0x4],edx
0x804841a   mov    DWORD PTR [esp],eax
0x804841d   call   0x8048300 <printf@plt>
0x8048422   mov    eax,ds:0x804a01c
0x8048427   mov    eax,DWORD PTR [eax]
0x8048429   mov    edx,DWORD PTR [eax]
0x804842b   mov    eax,0x8048520
0x8048430   mov    DWORD PTR [esp+0x4],edx
0x8048434   mov    DWORD PTR [esp],eax
0x8048437   call   0x8048300 <printf@plt>
1
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 22:36  [ТС] #7
Цитата Сообщение от alkagolik Посмотреть сообщение
на уровне процессора ( *pobj ).el == pobj->el. "->" просто удачное решение от создателей. Чтим, помним и уважаем.
Точно, то что надо! Спасибо!

Ну а ассемблер я пока не пойму

Добавлено через 6 часов 16 минут
А как насчет спецификатора класса памяти extern?
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
08.01.2012, 22:51 #8
Цитата Сообщение от Tamoren Посмотреть сообщение
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
может схавать - зависит от компилятора, но поведение неопределенное
1
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 23:46  [ТС] #9
То есть переменные, объявленные с extern и без должны иметь одинаковый тип, иначе я рискую нарваться на ошибку или вообще повредить память?
0
Evg
Эксперт CАвтор FAQ
18265 / 6389 / 440
Регистрация: 30.03.2009
Сообщений: 17,676
Записей в блоге: 28
09.01.2012, 12:43 #10
Цитата Сообщение от Tamoren Посмотреть сообщение
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
Конкретно в данном случае де-юре сам дурак, потому что программист обязан следить за корректностью описаний. Де-факто в случае языка Си скорее всего все компиляторы сожрут это, но в случае Си++, возможно, "int x" и "volatile int x" могут трактоваться как два разных объекта

Добавлено через 29 секунд
Цитата Сообщение от Tamoren Посмотреть сообщение
То есть переменные, объявленные с extern и без должны иметь одинаковый тип, иначе я рискую нарваться на ошибку или вообще повредить память?
Грубо говоря, да
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
09.01.2012, 14:24 #11
Цитата Сообщение от Evg Посмотреть сообщение
но в случае Си++, возможно, "int x" и "volatile int x" могут трактоваться как два разных объекта
ну вот, как не странно линковщик g++'а съел определение double x; и объявление extern int x;
скомпилировал и слинковал без проблем, что немного пугает
1
Evg
Эксперт CАвтор FAQ
18265 / 6389 / 440
Регистрация: 30.03.2009
Сообщений: 17,676
Записей в блоге: 28
09.01.2012, 15:20 #12
Цитата Сообщение от alex_x_x Посмотреть сообщение
ну вот, как не странно линковщик g++'а съел определение double x; и объявление extern int x;
скомпилировал и слинковал без проблем, что немного пугает
Возможно, я и гоню. Просто функция с параметрами разных типов манглируется, а вот манглируются ли переменные - хз. Просто какая-то мысль вертится в голове на предмет того, что с модификатором где-то что-то по другому трактовалось, но не помню где
1
LosAngeles
Заблокирован
09.01.2012, 19:07 #13
Цитата Сообщение от alex_x_x Посмотреть сообщение
может схавать - зависит от компилятора, но поведение неопределенное
от компилятора это не зависит, компилятор, встретив переменную допустим extern int x, поместит её в таблицу символов, если пройтись по такому объектному файлу objdump, то он покажет смещение *UND* для такой переменной и в коде везде будет обращаться с ней как с обычным интом, просто пока неизвестно его смещение. Во втором модуле можно определить этот самый x причём чем угодно, необязательно интом, можно структурой или указателем на функцию, линкеру это по барабану, ему нужно только смещение и имя идентификатора, во внутренние дела модуля он не лезет. Главное чтобы все были определены по разу, он просто слепит все модули подставив соответсвующие адреса. Он не делает проверку типов. Так что extern volatileint по всей видимости означает что внутри этого модуля с этим импортированным символом будут обращаться как с int volatile, но чем он является на самом деле неизвестно. Конечно это всё зависит от ABI, может на какой нибудь платформе с каким то экзотическим форматом файлов и делается проверка типов, но я с такими не сталкивался. Удобно кстати задефайнить extern в PUBLIC, а static в PRIVATE, тогда становится нагляднее что экспортируется


в системном программировании кстати применяется иногда такой трюк с extern. Иногда нужно например убедиться чтобы размер загрузочного образа был в рамках приличного на этапе компиляции, тогда пользуются тем фактом, что нельзя создать массив отрицательного размера
C
1
extern int dummy[sizeof(image) > LIMIT ? 100 : -100];
а потом определяют его где-нибудь dummy как short int
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
09.01.2012, 19:10 #14
LosAngeles, ок, от линковщика, но смысла это не меняет
0
LosAngeles
Заблокирован
09.01.2012, 19:22 #15
меняет, ТС запугали что ктото чтото не пропустит, на самом деле пропустит всё. В данном конкретном случае:
Цитата Сообщение от Tamoren Посмотреть сообщение
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
не пройзойдёт ничего, где-то переменная будет трактоваться как volatile, а где-то нет, это странно конечно но формально правильно
0
09.01.2012, 19:22
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.01.2012, 19:22
Привет! Вот еще темы с ответами:

Проверка выделения памяти указателей через оператор new - C++
И так есть некая структура, экземпляр которой определён как: var ***v; Изначально заполняю экземпляр: v = new var**; // создание...

Реализовать оператор умножения класса - C++
Только начал работать с классами и мне не совсем понятно, как работать с операторами, вот что у меня получилось: class Matrix { ...

Оператор присвоения для класса - C++
Никак не получается написать оператор присвоения. Помогите пожалуйста! #include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std;...

Шаблонный оператор не шаблонного класса - C++
Пытаюсь создать альтернативный оператор выделения памяти для своей библиотеки. С целью получить возможность передавать дополнительную...


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

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

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