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

Сложение указателей - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 5.00
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
01.05.2012, 18:01     Сложение указателей #1
Чисто декларативно замечу что это не безсмысленная операция, как нам о том повествуют всюду.
пример:
C++
1
2
3
    ExpressionEdit* a = split ? leftInsert : rightInsert;
    ExpressionEdit* b = split ? rightInsert : leftInsert;
    split = !split;
можно бы было реализовать без второй операции ветвления следующим образом:
C++
1
2
3
    ExpressionEdit* a = split ? leftInsert : rightInsert;
    ExpressionEdit* b = rightInsert + leftInsert - a;
    split = !split;
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
01.05.2012, 18:05     Сложение указателей #2
CEBEP, стандарт с вами не согласится

A subtraction of two pointers is only granted to have a valid defined value for pointers to elements of the same array (or for the element just past the last in the array).

For other values, the behavior depends on the system characteristics and compiler implementation.
кроме того второй код вразы психоделичней
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
01.05.2012, 18:21  [ТС]     Сложение указателей #3
Цитата Сообщение от alex_x_x Посмотреть сообщение
CEBEP, стандарт с вами не согласится
В чём конкретно он со мной не согласится? То что эти указатели не объедены массивом это весомый момент, но, думаю, степень гипотетичности всего выражения в целом позволяет закрыть на это глаза, ведь сложение указателей должно будет вернуть указатель который вовсе не обязан иметь смысл как таковой, а лишь должен быть использован как левый аргумент в операции вычитания.
Да и вообще что толку апеллировать к стандарту, если зашла речь о сущности которую он предал анафеме? Я просто хотел заметить что чисто алгебраически такая операция может иметь смысл.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
01.05.2012, 18:24     Сложение указателей #4
Цитата Сообщение от CEBEP Посмотреть сообщение
В чём конкретно он со мной не согласится? То что эти указатели указывают не объеденные массивом это весомый момент, но, думаю, степень гипотетичности всего выражения в целом позволяет закрыть на это глаза, ведь сложение указателей должно будет вернуть указатель который вовсе не обязан иметь смысл как таковой, а лишь должен быть использован как левый аргумент в операции вычитания.
разность указателей дает тип ptrdiff_t
то что нельзя просто так орудовать с указателями говорит стандарт и эта тема [Задача] Адресная арифметика
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
01.05.2012, 18:28     Сложение указателей #5
может быть и можно было бы второй вариант использовать, но для чего?
для обфускации, чтобы враги дольше код понимали?
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
01.05.2012, 18:45  [ТС]     Сложение указателей #6
Цитата Сообщение от DU Посмотреть сообщение
для чего?
по моему второй вариант должен выполнятся существенно быстрее
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
01.05.2012, 18:50     Сложение указателей #7
копеечная оптимизация, да и то не факт. нужно в асм смотреть после компиляции с оптимизацией или замеры делать. в любом случае на производительность программы в целом это врятли повлияет. зато код стал такой хитромудрый, что не каждый его сможет осознать.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
01.05.2012, 18:54     Сложение указателей #8
Цитата Сообщение от CEBEP Посмотреть сообщение
rightInsert + leftInsert - a;
по угару
если rightInsert и leftInsert у верхней границы адресов, то rightInsert + leftInsert может дать переполнение (на 32битах) и результатом будет невалидный указатель
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
01.05.2012, 18:55  [ТС]     Сложение указателей #9
Цитата Сообщение от DU Посмотреть сообщение
копеечная оптимизация
Не понимаю попытки доказать что это бессмысленно. Строго говоря, я обратного и не утверждал
Цитата Сообщение от alex_x_x Посмотреть сообщение
результатом будет невалидный указатель
да, я об этом прямо упоминал во втором своём сообщении...
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
01.05.2012, 19:09     Сложение указателей #10
C++
1
2
3
4
5
6
7
ExpressionEdit* a = rightInsert;
ExpressionEdit* b = leftInsert;
if (split) {
    a = leftInsert;
    b = rightInsert;
}
split = !split;
Оставьте уже машинную оптимизацию компилятору. Это его работа.

Добавлено через 1 минуту
Или даже так (хотя мне предыдущий больше по душе)
C++
1
2
3
4
5
6
7
8
9
10
ExpressionEdit* a;
ExpressionEdit* b;
if (split) {
    a = leftInsert;
    b = rightInsert;
} else {
    a = rightInsert;
    b = leftInsert;
}
split = !split;
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
01.05.2012, 19:15     Сложение указателей #11
вы ассемблерный код то хотябы видели?
у вас там две арифметические операции с указателями. значит будет один промежуточный результат, его нужно в регистрах хранить что-то делать с этим всем. + не забыть учесть, что в арифметике указателей еще неявно учавствует размер. т.е. возможно там еще и умножение в каждой операции будет
Вот какой ассемблер у меня получился в дебаге:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
  int* p1 = b ? left : right;
0041332E  movzx       eax,byte ptr [b] 
00413332  test        eax,eax 
00413334  je          F1+31h (413341h) 
00413336  mov         ecx,dword ptr [left] 
00413339  mov         dword ptr [ebp-0DCh],ecx 
0041333F  jmp         F1+3Ah (41334Ah) 
00413341  mov         edx,dword ptr [right] 
00413344  mov         dword ptr [ebp-0DCh],edx 
0041334A  mov         eax,dword ptr [ebp-0DCh] 
00413350  mov         dword ptr [p1],eax 
  int* p2 = b ? right : left;
00413353  movzx       eax,byte ptr [b] 
00413357  test        eax,eax 
00413359  je          F1+56h (413366h) 
0041335B  mov         ecx,dword ptr [right] 
0041335E  mov         dword ptr [ebp-0DCh],ecx 
00413364  jmp         F1+5Fh (41336Fh) 
00413366  mov         edx,dword ptr [left] 
00413369  mov         dword ptr [ebp-0DCh],edx 
0041336F  mov         eax,dword ptr [ebp-0DCh] 
00413375  mov         dword ptr [p2],eax 
*/
void F1(bool b, int* left, int* right)
{
  int* p1 = b ? left : right;
  int* p2 = b ? right : left;
}
 
/*
  int* p1 = b ? left : right;
00412E5C  movzx       eax,byte ptr [b] 
00412E60  test        eax,eax 
00412E62  je          F2+3Fh (412E6Fh) 
00412E64  mov         ecx,dword ptr [left] 
00412E67  mov         dword ptr [ebp-0F4h],ecx 
00412E6D  jmp         F2+48h (412E78h) 
00412E6F  mov         edx,dword ptr [right] 
00412E72  mov         dword ptr [ebp-0F4h],edx 
00412E78  mov         eax,dword ptr [ebp-0F4h] 
00412E7E  mov         dword ptr [p1],eax 
  int* p2 = left + x - y;
00412E81  mov         eax,dword ptr [x] 
00412E84  mov         ecx,dword ptr [left] 
00412E87  lea         edx,[ecx+eax*4] 
00412E8A  mov         eax,dword ptr [y] 
00412E8D  shl         eax,2 
00412E90  sub         edx,eax 
00412E92  mov         dword ptr [p2],edx 
*/
void F2(bool b, int* left, int* right)
{
  int x = 10;
  int y = 20;
  int* p1 = b ? left : right;
  int* p2 = left + x - y;
}
 
 
/*
  int* p1 = right;
0041277E  mov         eax,dword ptr [right] 
00412781  mov         dword ptr [p1],eax 
  int* p2 = left;
00412784  mov         eax,dword ptr [left] 
00412787  mov         dword ptr [p2],eax 
  if (b)
0041278A  movzx       eax,byte ptr [b] 
0041278E  test        eax,eax 
00412790  je          F3+3Eh (41279Eh) 
  {
    p1 = right;
00412792  mov         eax,dword ptr [right] 
00412795  mov         dword ptr [p1],eax 
    p2 = left;
00412798  mov         eax,dword ptr [left] 
0041279B  mov         dword ptr [p2],eax 
  }
*/
void F3(bool b, int* left, int* right)
{
  int* p1 = right;
  int* p2 = left;
  if (b)
  {
    p1 = right;
    p2 = left;
  }
}

Если вы специалист - считайте такты. Кстати, ваш код даже не компилируется в студии.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
01.05.2012, 19:26     Сложение указателей #12
Цитата Сообщение от DU Посмотреть сообщение
Кстати, ваш код даже не компилируется в студии.
Ну он и не говорил, что компилируется. Это были размышления на тему "Ах если бы, ах если бы... Не жизнь была, а песня бы..."

Добавлено через 6 минут
Кстати, даже если допустить правильность и полезность подобной конструкции, то сложение указателей всё-равно не нужно.
C++
1
ExpressionEdit* b = rightInsert + (leftInsert - a);
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
01.05.2012, 19:26     Сложение указателей #13
Ну можно тогда вообще так
C++
1
flag ? ( a = b, c = d ) : ( a = d, c = b );
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
01.05.2012, 19:35  [ТС]     Сложение указателей #14
Цитата Сообщение от DU Посмотреть сообщение
Кстати, ваш код даже не компилируется в студии.
Второй вариант кода я и не пытался компилировать потому что был уверен что он не должен был компилироваться. То что у вас есть компилятор который это проглотил меня удивило.

Цитата Сообщение от grizlik78 Посмотреть сообщение
сложение указателей всё-равно не нужно.
ну в том варианте в котором вы предложили есть ссылка на
Цитата Сообщение от alex_x_x Посмотреть сообщение
A subtraction of two pointers is only granted to have a valid defined value for pointers to elements of the same array (or for the element just past the last in the array). For other values, the behavior depends on the system characteristics and compiler implementation.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
01.05.2012, 20:04     Сложение указателей #15
Цитата Сообщение от CEBEP Посмотреть сообщение
То что у вас есть компилятор который это проглотил меня удивило
Нет у него такого компилятора. Там просто целые складываются.


Цитата Сообщение от CEBEP Посмотреть сообщение
ну в том варианте в котором вы предложили есть ссылка на
A subtraction of two pointers is only granted to have a valid defined value for pointers to elements of the same array (or for the element just past the last in the array). For other values, the behavior depends on the system characteristics and compiler implementation.
Разумеется. Но это-то, кстати, можно предусмотреть, выделяя элементы из одного массива
Но Баба-Яга всё-равно против

Добавлено через 25 минут
Ну и чтобы показать, насколько программист может усложнить "жизнь" компилятору, посмотрим, что делает GCC4.5 в режиме оптимизации -O3
Скомпилированы следующие 3 функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bool F1(bool b, int* left, int* right)
{
  int* p1 = b ? left : right;
  int* p2 = b ? right : left;
  return p1 > p2;
}
 
bool F2(bool b, int* left, int* right)
{
  int* p1 = b ? left : right;
  int* p2 = left + (right - p1);
  return p1 > p2;
}
 
bool F3(bool b, int* left, int* right)
{
  int* p1 = right;
  int* p2 = left;
  if (b)
  {
    p1 = left;
    p2 = right;
  }
  return p1 > p2;
}
Первая породила такой код:
Assembler
1
2
3
4
5
6
7
8
9
    .cfi_startproc
    testb   %dil, %dil
    movq    %rsi, %rax
    cmove   %rdx, %rax
    cmovne  %rdx, %rsi
    cmpq    %rsi, %rax
    seta    %al
    ret
    .cfi_endproc
Ну, в общем, что просили, то и получили.

Из второй вышло такое:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    .cfi_startproc
    xorl    %eax, %eax
    testb   %dil, %dil
    je  .L5
    movq    %rdx, %rax
    movq    %rsi, %rdx
    subq    %rsi, %rax
    andq    $-4, %rax
.L5:
    addq    %rax, %rsi
    cmpq    %rsi, %rdx
    seta    %al
    ret
    .cfi_endproc
Разве стало эффективнее? В прошлый раз были условные пересылки, но не было ветвления. Здесь же увы, условный переход.

Третий код оказался идентичным первому.
Assembler
1
2
3
4
5
6
7
8
9
    .cfi_startproc
    testb   %dil, %dil
    movq    %rsi, %rax
    cmovne  %rdx, %rax
    cmove   %rdx, %rsi
    cmpq    %rax, %rsi
    seta    %al
    ret
    .cfi_endproc
Вариант Toshkarik даёт тоже точно такой код.
Выбирайте

DU, у тебя в третьей функции ошибка. По условию выполняется то же, что и без условия.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
01.05.2012, 20:15     Сложение указателей #16
ну да, есть такое. оптимизатор мог бы вообще удалить проверки буля и всего того, что в ифе написано. код стал бы мегаоптимальным .
Возвращаясь к предпосылкам возникновения темы: нехер писать подобного рода оптимизации, даже если они реально более оптимальны. выйгрыш копеечный. главное чтобы код оставался чистым, понимаемым, сопровождаемым. а то ведь если все писать в таком духе, где черт ногу словит, но зато "оптимально" одно случайное преобразование типа (скажем из конст чара в строку) из-за динамического выделения памяти в тыщу раз перекроет все эти потуги ради пары тактов.
Впрочем, до понимания этих вещей нужно еще дорасти. Просто советы не работают. На себе проверено
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.05.2012, 20:15     Сложение указателей
Еще ссылки по теме:

Создать специализацию для шаблона, которая принимает массив указателей на строки и количество этих указателей C++
Создать специфицированный шаблон функции, принимающей массив указателей на char и количество самих указателей C++
Массив указателей C++

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

Или воспользуйтесь поиском по форуму:
CEBEP
105 / 105 / 9
Регистрация: 21.03.2010
Сообщений: 437
01.05.2012, 20:15  [ТС]     Сложение указателей #17
Всё таки зря я попытался искать в этой операции практическую суть. И тем не менее, ведь такое поведение связанно как раз с тем, что как такового сложения указателей не происходит.
Yandex
Объявления
01.05.2012, 20:15     Сложение указателей
Ответ Создать тему
Опции темы

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