61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 354
Записей в блоге: 3
1

Почему поинтер обнуляется ?

30.04.2019, 02:01. Показов 6497. Ответов 118
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
 
 
int main()
{
 char* p = (char*)malloc(strlen("Thunderbird") + 1);
  strcpy(p, "Thunderbird");
for ( ; *p; ++p) if(*p > 'Z') {continue;} else if (*p < 'A') {continue;} else {*p = *p|0x60;}
 
printf ("str3 = %s ",p);
}
почему for обнуляет вместо того чтобы присвоить ?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.04.2019, 02:01
Ответы с готовыми решениями:

Почему все обнуляется???
#include &lt;iostream.h&gt; #include &lt;iomanip.h&gt; // прототипы функций void input ( float , char);...

Почему мой указатель обнуляется?
Почему мой указатель обнуляется на какой-то итерации? задача: Функцию, которая возвращает среднее...

Почему не обнуляется указатель через функцию?
В функцию передаю указатель на целое число, хочу удалить память а сам указатель установить в NULL. ...

В определенный момент массив почему-то обнуляется
Вот листинг: #include &lt;fstream&gt; #include &lt;iostream&gt; using namespace std; double _AverageGain;...

118
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 18:02 41
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от alexbmd Посмотреть сообщение
почему? если префиксный инкремент две инструкции а пост инкремент три.
Для фундаментальных типов не будет разницы в сгенерированном коде между префиксной и постфиксной формой.
0
Вездепух
Эксперт CЭксперт С++
11689 / 6368 / 1723
Регистрация: 18.10.2014
Сообщений: 16,051
14.05.2019, 18:10 42
Цитата Сообщение от alexbmd Посмотреть сообщение
почему? если префиксный инкремент две инструкции а пост инкремент три.
Это откуда вы взяли такую странную информацию??

Для фундаментального типа, т.е. типа, поддерживаемого на уровне компилятора, в контексте, где результат ++ игнорируется, любой вменяемый компилятор всегда сгенерирует соверешенно идентичный - оптимальный - код и для префиксного ++, и для постфиксного ++. Количество инструкций будет совершенно идентичным.
1
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 354
Записей в блоге: 3
14.05.2019, 18:25  [ТС] 43
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
в контексте, где результат ++ игнорируется
а если результат участвует в дальнейших вычеслениях и оптимизации компилятора отключенны то разница так понимаю будет ?
0
Вездепух
Эксперт CЭксперт С++
11689 / 6368 / 1723
Регистрация: 18.10.2014
Сообщений: 16,051
14.05.2019, 18:31 44
Цитата Сообщение от alexbmd Посмотреть сообщение
а если результат участвует в дальнейших вычеслениях
Зависит от этих "дальнейших вычислений". Правило тот простое: используйте именно тот оператор, который нужен в данном контексте. А компилятор уже сам разберется, как сгенерировать оптимальный код.

Цитата Сообщение от alexbmd Посмотреть сообщение
и оптимизации компилятора отключенны то разница так понимаю будет ?
Таки вещи никак не зависят от включенных или выключенных "оптимизаций компилятора".
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 19:02 45
alexbmd, вы не увидите разницы ни при каких-либо явно включённых оптимизациях, ибо для фундаментальных типов инкремент (+1) выполнит процессор и здесь не может быть никаких отличий.
Например возьмём цикл for (int i = 0; i < 10000; i++), здесь операция i++ хорошо определена и нам точно известен порядок вычисления по отношению к остальным выражениям, до и после i++ и в любом случае все что здесь нам надо это увеличить i на 1 и именно это мы всегда получим в сгенерированном коде, внезависимости от того будет ли это постфиксный или префиксный инкремент.
Более того в некоторых случаях в циклах префиксный инкремент может ввести зависимость от данных в ваш код
0
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,768
14.05.2019, 19:10 46
Цитата Сообщение от Azazel-San Посмотреть сообщение
Более того в некоторых случаях в циклах префиксный инкремент может ввести зависимость от данных в ваш код
А можно поподробнее(или ссылку)?
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 19:14 47
zayats80888, Game Engine Architecture (3rd edition), там есть топик посвящённый этому.
0
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 354
Записей в блоге: 3
14.05.2019, 19:18  [ТС] 48
просто читал что ранее когда я был молодой, синтактический сахар использовали как раз для того что была разница как прибавлять. потом уже компилятор научился ассемблировать одинаковый код. но я подумал отключив все оптимизации компилятора пост и пре инкремент в какихто особых случаях разница будет. ну нет так нет. доверимся компилятору спасибо

Azazel-San, ну вот for плохой пример для этого. тут разницы нету и так и так
for(;;++i) print i
for(;;i++) print i
//результат одинаковый

хотя бы вот
for(;++i; ) print i
for(;i++; ) print i
//тут я думал может получиться разный код (ну только более сложный пример нужен конечно). но нет так нет

просто почемуто именно сишник очень любят префиксный инкремент. хотя для большинства простых задач нужен как раз постфикс.
++i чаще для простых задач только путаницу добовляет/читаемость кода падает. понятно что можно любой код подстроить до правильного результата. ну это имхо конечно
0
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,768
14.05.2019, 19:21 49
Цитата Сообщение от Azazel-San Посмотреть сообщение
Game Engine Architecture (3rd edition)
Вы мне предлагаете аж целую книжку купить Повременю пока. Ну в двух словах, если это возможно, объясните.

Добавлено через 2 минуты
Цитата Сообщение от alexbmd Посмотреть сообщение
хотя для большинства простых задач нужен как раз постфикс.
Ну вот открыл библиотеку <algorithm> и вижу в арифметике итераторов везде префиксный инкремент/декремент(если явно не требуется постфиксный) Ну и книжка Страуструпа приучила меня к такомуже подходу, а он то уж точно не "сишник"
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 19:55 50
Цитата Сообщение от zayats80888 Посмотреть сообщение
Ну в двух словах, если это возможно, объясните.
Допустим у нас есть такой код:
C++
1
2
3
4
5
6
7
8
void process_array(int const* container, std::size_t const num_elements) {
   int* begin = &container[0];
   int* end   = &container[num_elements];
   for (int* p = begin; p != end; p++) {
      int element = *p;
      // process element...
   }
}
В примере process_array() мы используем постинкрементный оператор, p++. Это тонкая, но иногда важная оптимизация. Оператор preincrement увеличивает содержимое переменной до того, как ее (теперь измененное) значение используется в выражении. Оператор postincrement увеличивает содержимое переменной после ее использования. Это означает, что написание ++p вводит зависимость данных в ваш код - CPU должен дождаться завершения операции инкремента, прежде чем его значение можно будет использовать в выражении. На глубоко конвейерном процессоре, это приводит к остановке. С другой стороны, с p++ нет зависимости. Значение переменной можно использовать немедленно, а операция приращения может произойти позже или параллельно с ее использованием.
Конечно, в выражении «update» цикла for не должно быть различий между пре- и постинкрементами. Это потому, что любой хороший компилятор распознает, что значение переменной не используется в update_expr. Но в тех случаях, когда используется значение, постинкремент предпочтительнее, поскольку он не приводит к задержке в конвейере CPU.
Цитата Сообщение от zayats80888 Посмотреть сообщение
и вижу в арифметике итераторов везде префиксный инкремент/декремент
Может быть целесообразно сделать исключение из этого небольшого практического правила для классов с перегруженными операторами приращения, как это принято в классах итераторов. По определению оператор постинкремента должен возвращать неизмененную копию объекта, для которого он вызывается. В зависимости от размера и сложности элементов данных класса, дополнительная стоимость копирования итератора может склонить шкалы к предпочтению преинкремента при использовании таких классов в циклах, критичных к производительности

Добавлено через 11 минут
Цитата Сообщение от alexbmd Посмотреть сообщение
хотя бы вот
for(;++i; ) print i
for(;i++; ) print i
//тут я думал может получиться разный код
Каким образом?
И как вы определяли разный код здесь или нет?
Цитата Сообщение от alexbmd Посмотреть сообщение
++i чаще для простых задач только путаницу добовляет/читаемость кода падает. понятно что можно любой код подстроить до правильного результата. ну это имхо конечно
Постфиксный или префиксный операторы инкремента это лишь еще один инструмент для написания оптимального и эффективного кода для железа. Смотри выше.
Позволю себе уже во второй раз за сегодня скопировать цитату, которую мне сказали:
Ты пишешь код и выражаешь мысль, современный код это и инструкции для процессора (в конечном счете) и роман для другого программиста. Поэтому как роман составленный из шаблонов из методички будет смотреться "не очень", так и программа, наполненная бездумно вставленным кодом, обоснование которому "так принято", - тоже.
1
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,768
14.05.2019, 20:00 51
Цитата Сообщение от Azazel-San Посмотреть сообщение
Оператор preincrement увеличивает содержимое переменной до того, как ее (теперь измененное) значение используется в выражении.
правильно ли я понял, что в данном случае оптимизация в том, что постинкремент выполняется не в конце итерации а в начале? Т. е. p!=end->p++-><тело цикла, работаем с значением p до инкремента>?
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 20:05 52
Цитата Сообщение от zayats80888 Посмотреть сообщение
<тело цикла, работаем с значением p до инкремента>
Да, мы работаем с переменной до того, как ее увеличат в выражении и мы можем работать с p как оно есть и только потом сделать инкремент.
У нас нету зависимости от инкремента, и мы можем сделать некие оптимизации в этом контексте.
1
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 354
Записей в блоге: 3
14.05.2019, 20:19  [ТС] 53
Цитата Сообщение от Azazel-San Посмотреть сообщение
Каким образом?
И как вы определяли разный код здесь или нет?
речь не конкретно про этот код. а в целом. если пре инкремент это 2 инструкции а пост - 3 то на каких то как вы говорите критичных к производительности кусках кода
" дополнительная стоимость копирования итератора может склонить шкалы к предпочтению преинкремента при использовании таких классов в циклах, критичных к производительности"
мы можем увидеть разницу.
раньше я об этом не задумывался но теперь не удевлюсь если разница таки будет пусть и микроскопическая.

Добавлено через 9 минут
Цитата Сообщение от zayats80888 Посмотреть сообщение
p!=end->p++-><тело цикла, работаем с значением p до инкремента>
Azazel San мы в обоих случаях работаем с одинаковым значением.

p=0;
p!=end -> p++ -> print p//0 -> p=1 -> p!=end ->
p!=end -> ++p -> print p//0 -> p=1 -> p!=end ->

вот и Калиграфер говорит
"Третий сегмент из заголовка for выполняется в конце каждой итерации."

ну там понятно разница в инкременте есть, но в теле лупа оно нам не видно

PS: не спора ради а просветления для
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 20:23 54
Цитата Сообщение от zayats80888 Посмотреть сообщение
тело цикла
Только щас заметил, не в теле цикла.
В теле цикла мы уже будем работать с увеличенным значением.

Добавлено через 1 минуту
Цитата Сообщение от alexbmd Посмотреть сообщение
Azazel San мы в обоих случаях работаем с одинаковым значением.
В теле цикла да, я почему то, подумал о другом и не заметил что здесь именно о теле цикла речь зашла.

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

Не по теме:

Странно, обновил страницу и мне репутацию списали, хм..

0
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,768
14.05.2019, 20:31 55
Цитата Сообщение от Azazel-San Посмотреть сообщение
В теле цикла мы уже будем работать с увеличенным значением.
я подумал что то вроде этого, например
p!=end->p++-><тело цикла, работаем с значением p до инкремента>->p!=end->(т.к. p уже прирастили можно не ожидать, а сразу в тело нырять, где-нибудь параллельно опять прирастим)<тело цикла, работаем с увеличенным в прошлый раз значением p>->(если не прирастили, ожидаем) и т.д.
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 20:50 56
zayats80888, смотрите, вот ключевые фразы:
Цитата Сообщение от Azazel-San Посмотреть сообщение
Конечно, в выражении «update» цикла for не должно быть различий между пре- и постинкрементами. Это потому, что любой хороший компилятор распознает, что значение переменной не используется в update_expr.
Здесь может быть немного запутанно, что имеет ввиду автор, но вот как иногда описывают цикл for:
Код
for (initialization-expression; declaration-or-test-expression; update-expression)
update_expr - это именно так секция где идет обновление счетчика, обычно мы его хотим видеть в последнем блоке цикла, но это не всегда так, в примере выше я тоже его разместил в конце, просто из-за удобства.
И вот если это значение update не используется выхлоп будет одинаковым.

И это:
Цитата Сообщение от Azazel-San Посмотреть сообщение
Но в тех случаях, когда используется значение, постинкремент предпочтительнее, поскольку он не приводит к задержке в конвейере CPU.
Когда же приходит тот момент использования?
Например в чем-то таком:
C++
1
for(int i = 0; arr[i++];)
1
6091 / 3449 / 1402
Регистрация: 07.02.2019
Сообщений: 8,768
14.05.2019, 21:17 57

Не по теме:

Надеюсь не задолбал еще :)


C++
1
2
3
4
5
6
7
8
9
10
    //это конечно упрощение
    int val{};
    for (int i = 0; i < 10;)
        val += ++i;
 
    // не смотря на одинаковый результат имеет смысл перестроить
    // под постинкремент для оптимизации?
    val = 0;
    for (int i = 1; i < 11;)
        val += i++;
0
Mental handicap
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
14.05.2019, 23:31 58
Цитата Сообщение от Azazel-San Посмотреть сообщение
Например в чем-то таком:
Весьма не удачный пример, т.к. обращение к массиву компилятор всеравно может выкинуть
Вот, например что-то такое
https://godbolt.org/z/NEYHpe
Цитата Сообщение от zayats80888 Посмотреть сообщение
Надеюсь не задолбал еще
Да, вероятно имеет, результат постинкремента можно использовать и параллельно на другом конвейере инкремент выполнить.
Цитата Сообщение от zayats80888 Посмотреть сообщение
// не смотря на одинаковый результат имеет смысл перестроить
* * // под постинкремент для оптимизации?
Опять же, нужно смотреть конкретный asm-код.

Может, ув. TheCalligrapher, пролил бы свет
1
4063 / 3317 / 924
Регистрация: 25.03.2012
Сообщений: 12,483
Записей в блоге: 1
15.05.2019, 00:13 59
Цитата Сообщение от zayats80888 Посмотреть сообщение
// не смотря на одинаковый результат имеет смысл перестроить // под постинкремент для оптимизации?
впервые такое слышу. Обычно считается, что прединкремент оптимальнее постинкремента, хоть и не советуют заморачиваться с такого рода "оптимизацией".
0
Вездепух
Эксперт CЭксперт С++
11689 / 6368 / 1723
Регистрация: 18.10.2014
Сообщений: 16,051
15.05.2019, 00:28 60
Цитата Сообщение от zayats80888 Посмотреть сообщение
// не смотря на одинаковый результат имеет смысл перестроить
* * // под постинкремент для оптимизации?
Нет, разумеется. Никакого смысла в такой оптимизации для инкремента скалярного типа нет.
0
15.05.2019, 00:28
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.05.2019, 00:28
Помогаю со студенческими работами здесь

Почему во время чтения из файла переменная row_i в цикле постоянно обнуляется?
Имеется следующий код: #include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; int...

Переполнение знаковых целых чисел: почему значение переменной обнуляется, а не записывается младшее значение?
что то не пойму, как происходит переполнение знаковых целых чисел вот #include &lt;iostream&gt; ...

Почему массив не обнуляется
Не знаю почему массив не обнуляется. #include &quot;stdafx.h&quot; #include &lt;stdio.h&gt; #include &lt;math.h&gt;...

Не обнуляется таймер почему-то
procedure TForm1.Button1Click(Sender: TObject); begin Timer1.Enabled:=True; ...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru