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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.73
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 02:40     Оператор -> и спецификатор класса памяти extern #1
Оператор ->
Исходя из того, что он вообще был добавлен в язык, можно сделать вывод, что такая *struct.elem запись уже где-то используется (не для доступа к элементу elem структуры struct), и оператор -> добавлен для того чтобы избежать путаницы (и используется такая struct->elem запись). Вопрос: где используется такая *struct.elem запись?

Cпецификатор класса памяти extern
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.01.2012, 02:44     Оператор -> и спецификатор класса памяти extern #2
например
Цитата Сообщение от Tamoren Посмотреть сообщение
Вопрос: где используется такая *struct.elem запись?
C
1
2
3
4
5
struct mystruct {
    int* elem;
} obj;
//...
*obj.elem = 100500;
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 03:05  [ТС]     Оператор -> и спецификатор класса памяти extern #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...
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
08.01.2012, 04:19     Оператор -> и спецификатор класса памяти extern #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/e902e6...535ce62e385fcb
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 06:18  [ТС]     Оператор -> и спецификатор класса памяти extern #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 << ", ";
Вроде работает правильно. Смысл понял. Дело было в более высоком приоритете "." или "->" (над "*").
alkagolik
 Аватар для alkagolik
1510 / 616 / 79
Регистрация: 15.07.2011
Сообщений: 3,552
08.01.2012, 12:53     Оператор -> и спецификатор класса памяти extern #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/995898...055fc659959671
на уровне процессора ( *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>
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 22:36  [ТС]     Оператор -> и спецификатор класса памяти extern #7
Цитата Сообщение от alkagolik Посмотреть сообщение
на уровне процессора ( *pobj ).el == pobj->el. "->" просто удачное решение от создателей. Чтим, помним и уважаем.
Точно, то что надо! Спасибо!

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

Добавлено через 6 часов 16 минут
А как насчет спецификатора класса памяти extern?
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
08.01.2012, 22:51     Оператор -> и спецификатор класса памяти extern #8
Цитата Сообщение от Tamoren Посмотреть сообщение
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
может схавать - зависит от компилятора, но поведение неопределенное
Tamoren
0 / 0 / 0
Регистрация: 08.01.2012
Сообщений: 37
08.01.2012, 23:46  [ТС]     Оператор -> и спецификатор класса памяти extern #9
То есть переменные, объявленные с extern и без должны иметь одинаковый тип, иначе я рискую нарваться на ошибку или вообще повредить память?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16843 / 5264 / 323
Регистрация: 30.03.2009
Сообщений: 14,159
Записей в блоге: 26
09.01.2012, 12:43     Оператор -> и спецификатор класса памяти extern #10
Цитата Сообщение от Tamoren Посмотреть сообщение
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
Конкретно в данном случае де-юре сам дурак, потому что программист обязан следить за корректностью описаний. Де-факто в случае языка Си скорее всего все компиляторы сожрут это, но в случае Си++, возможно, "int x" и "volatile int x" могут трактоваться как два разных объекта

Добавлено через 29 секунд
Цитата Сообщение от Tamoren Посмотреть сообщение
То есть переменные, объявленные с extern и без должны иметь одинаковый тип, иначе я рискую нарваться на ошибку или вообще повредить память?
Грубо говоря, да
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
09.01.2012, 14:24     Оператор -> и спецификатор класса памяти extern #11
Цитата Сообщение от Evg Посмотреть сообщение
но в случае Си++, возможно, "int x" и "volatile int x" могут трактоваться как два разных объекта
ну вот, как не странно линковщик g++'а съел определение double x; и объявление extern int x;
скомпилировал и слинковал без проблем, что немного пугает
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16843 / 5264 / 323
Регистрация: 30.03.2009
Сообщений: 14,159
Записей в блоге: 26
09.01.2012, 15:20     Оператор -> и спецификатор класса памяти extern #12
Цитата Сообщение от alex_x_x Посмотреть сообщение
ну вот, как не странно линковщик g++'а съел определение double x; и объявление extern int x;
скомпилировал и слинковал без проблем, что немного пугает
Возможно, я и гоню. Просто функция с параметрами разных типов манглируется, а вот манглируются ли переменные - хз. Просто какая-то мысль вертится в голове на предмет того, что с модификатором где-то что-то по другому трактовалось, но не помню где
LosAngeles
Заблокирован
09.01.2012, 19:07     Оператор -> и спецификатор класса памяти extern #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
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
09.01.2012, 19:10     Оператор -> и спецификатор класса памяти extern #14
LosAngeles, ок, от линковщика, но смысла это не меняет
LosAngeles
Заблокирован
09.01.2012, 19:22     Оператор -> и спецификатор класса памяти extern #15
меняет, ТС запугали что ктото чтото не пропустит, на самом деле пропустит всё. В данном конкретном случае:
Цитата Сообщение от Tamoren Посмотреть сообщение
Что произойдет, если в одном месте переменная определена как int, а в другом её объявить extern volatile int? Другими словами, что произойдет при использовании extern с по-другому объявленными переменными?
не пройзойдёт ничего, где-то переменная будет трактоваться как volatile, а где-то нет, это странно конечно но формально правильно
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
09.01.2012, 19:27     Оператор -> и спецификатор класса памяти extern #16
LosAngeles, скорее всего да, но ровно также можно объявить и определить переменную с принципиально разными типами
и при доступе к ней получить неправильное значение и с некоторой вероятностью программное прерывание (если размеры объявления и определения не будут совпадать)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.01.2012, 21:40     Оператор -> и спецификатор класса памяти extern
Еще ссылки по теме:

C++ Проверка выделения памяти указателей через оператор new
Шаблонный оператор не шаблонного класса C++
Как грамотно убрать класс с глобальной видимости, удалив оператор extern? C++

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

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16843 / 5264 / 323
Регистрация: 30.03.2009
Сообщений: 14,159
Записей в блоге: 26
09.01.2012, 21:40     Оператор -> и спецификатор класса памяти extern #17
Цитата Сообщение от alex_x_x Посмотреть сообщение
LosAngeles, скорее всего да, но ровно также можно объявить и определить переменную с принципиально разными типами
и при доступе к ней получить неправильное значение и с некоторой вероятностью программное прерывание (если размеры объявления и определения не будут совпадать)
Можно. Плохо будет только тогда, когда реальная переменная меньше, чем то, что описано в extern'е, потому что в этом случае произойдёт выход за границу переменной и может затереться что-то полезное

C
1
2
3
4
5
6
7
8
9
10
11
12
13
/* Файл t1.c */
 
extern long long x;
 
extern void func (void);
 
int
main (void)
{
  x = 0x1122334455667788ull;
  func();
  return 0;
}
C
1
2
3
4
5
6
7
8
9
10
11
12
/* Файл t2.c */
 
#include <stdio.h>
 
int x = 0;
int y = 0;
 
void
func (void)
{
  printf ("x=0x%x, y=0x%x\n", x, y);
}
Код
$ gcc t1.c t2.c      
$ ./a.out 
x=0x55667788, y=0x11223344
Здесь мы затёрли переменную "y"
Yandex
Объявления
09.01.2012, 21:40     Оператор -> и спецификатор класса памяти extern
Ответ Создать тему
Опции темы

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