Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.88/34: Рейтинг темы: голосов - 34, средняя оценка - 4.88
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3

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

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

Студворк — интернет-сервис помощи студентам
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)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
30.04.2019, 02:01
Ответы с готовыми решениями:

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

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

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

118
15.05.2019, 00:36  [ТС]
Студворк — интернет-сервис помощи студентам

Не по теме:

всем чаю и спать :)

0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
15.05.2019, 12:23
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Обычно считается, что прединкремент оптимальнее постинкремента
Это если не брать в учет фундаментальные типы.
Ведь фундаментальный тип процессор может засунуть целиком в регистр, и инкремент этой переменной обычно это одна команда, что-то например
Assembler
1
2
3
4
...
mov eax, value
add eax, 1 ; increment by 1
...
Здесь нечему быть уже скорее, не важно пре- или постинкремент был использован, ведь здесь это увеличение будет делать процессор.

TL; DR
По поводу, пре- против постинкремента, это просто полезный хак, который, я считаю стоит запомнить, кто знает что может пригодится в жизни.
...
По поводу практических примеров, они есть, но исскуственно это симулировать имеет, наверное, весьма мало смысла. Я бы сказал, что пример можно было бы предоставить, если бы компиляторы всегда генерировали один и тот же код для одними тех же конструкций, но сейчас это не так - в зависимости от алгоритма, ключей компилятора, и т.д. одни и те же инструкции в разных контекстах могут превращаться в совершенно разный код, вплоть до того, что он вообще будет не похож на изначальный, но будет давать тот же результат.
Т.е. заморачиватся сильно не стоит, покрайней мере это опять же не очередное правило, мол так делай всегда, а так нет. Для обычного увеличения счетчика для перебора массива, например, можно использовать что нравится, т.к. выхлоп что для пост-, что для преинкремента будет одинаковый, а где нужно конкретное поведение конкретного оператора, тогда уже стоит тот и использовать.
Только типо если посмотрю на выхлоп компилятора, и меня там что-то не устроит по быстродействию, я могу вспомнить, что, ага, а вот может если здесь поменять с пре- на постинкремент я получу распараллеливание.
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
19.06.2019, 18:34  [ТС]
Друзья добрый день
новая непонятка

C++
1
2
3
4
5
6
7
8
const char *pa[] = {"dog", "mouse", "cat", "\0"};
 
for (char **list = (char**)pa; *list; ++list)
{
    cout << *list;
    
    printf(" *pa[] = %p\n",  list); 
}
если закоментить принт то печатает как и ожидается три строчки
а вот с принтом
C++
1
2
3
4
dog *pa[] = 0x7ffdc2e95c90                                                                                                                                                           
mouse *pa[] = 0x7ffdc2e95c98                                                                                                                                                         
cat *pa[] = 0x7ffdc2e95ca0                                                                                                                                                           
 *pa[] = 0x7ffdc2e95ca8
откуда берется 4 строчка? for же не долже заходить в луп после третей ? он и не заходит если закоментить принт. принт ни как не влияет на фор. почему идёт еще одна итерация?
0
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4574 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
19.06.2019, 18:44
Цитата Сообщение от alexbmd Посмотреть сообщение
откуда берется 4 строчка?
Да потому, что у Вас массив из адресов четырех строк.
Последний адрес - адрес строки "\0". Но сам адрес-то - ненулевой! Сделайте так:
C++
1
const char *pa[] = {"dog", "mouse", "cat", NULL};
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
19.06.2019, 18:52
C++
1
for (char **list = (char**)pa; **list; ++list)
Терминирующий ноль 1 символ.
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
19.06.2019, 19:23  [ТС]
Цитата Сообщение от liv Посмотреть сообщение
Да потому, что у Вас массив из адресов четырех строк.
так я её и добавил по совету Azazel, TheCalligrapher и других её не было вначале
и NULL который я вначале добавил тоже сказали неправильно. самое правильное именно "\0"
если что меня поправят
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
19.06.2019, 19:30
alexbmd, там вам сказали в каком-то контексте, который отсюда не виден. Так что то, что могло быть правильно в том контексте, в этом уже не будет правильным. Вот вы написали такой цикл, который проверяет указатель на ноль, и контекст сменился, а значит и советы все утратили силу. И надо заново голову включать
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
19.06.2019, 19:38  [ТС]
Azazel-San, DrOffset,
вот так работает
C++
1
2
3
4
5
const char *pa[] = {"dog", "mouse", "cat", 0};
for (char **list = (char**)pa; *list; ++list)
{
    cout << "-" << *list;
}
но так неправильно как я понял да ? в каком то компиляторе пройдёт финт а гдето нет

PS: это этот контекст

Добавлено через 7 минут
Цитата Сообщение от Azazel-San Посмотреть сообщение
Терминирующий ноль 1 символ.
это вы про то что я написал "\0" ?
так работает у меня в двух компиляторах . если пишу '\0' то в одном не работает
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
19.06.2019, 19:50
Цитата Сообщение от alexbmd Посмотреть сообщение
но так неправильно как я понял да ?
Почему это? Это правильно. Это тоже самое, что вариант с NULL.

Добавлено через 50 секунд
Цитата Сообщение от alexbmd Посмотреть сообщение
это вы про то что я написал "\0" ?
Это про то, что чтобы этот ноль проверить, нужно разыменовать оба указателя.

Добавлено через 6 минут
Цитата Сообщение от alexbmd Посмотреть сообщение
PS: это этот контекст
Я вам не верю. Покажите где это было
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
20.06.2019, 13:35
alexbmd,
C++
1
for (char **list = (char**)pa; **list; ++list)
Тогда будете сравнивать с нулём первый символ строки, а не адрес строки.
0
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
20.06.2019, 15:27  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Я вам не верю. Покажите где это было

да, там был while а не for но смысл тот-же

...так чтото я в очередной раз запутался

повторение-мать учения, еще раз:
цель: распечатать n строковых литерал , не указывая точное их кол-во. используя while.

тезис 1: есть только два способа прямой инициализациио строковых литерал без указания длины, так ?
C++
1
2
const char ma[][6] = {"dog", "mouse", "cat"};
const char   *pa[] = {"dog", "mouse", "cat"};
для выполнения нашей цели
тезис 2: в случае массива, обязательно надо указать последний терминирующий элемент. единственно верно так, а не NULL и т.д. ?
C++
1
const char ma[][6] = {"dog", "mouse", "cat", "\0"};
тезис 3: ну и перебрать массив, единственный верный способ по значению, так ?
C++
1
2
int i = 0;
while (*pa[i]) printf("ma[%d] = %s\n", i-1 , pa[i++]);
а вот тут начинаются непонятки...
тезис 4: в случае списка ссылок, обезательно указывать дополнительный терминирующий элемент ?
C++
1
2
//пример без терминатора
while (pa[i]) printf("pa[%d] = %s\n", i-1 , pa[i++]); //и работает, правда только в одном компиляторе
тезис 5.0: для списка ссылок, терминирующий элемент как 0 так правильно ?
C++
1
const char   *pa[] = {"dog", "mouse", "cat", 0};
тезис 5.1: этот 0 получается самим адресом ? но почему он получается самим адресом а не значением ?
вот смотрите атачмент. на размерность не обращяйте внимание, на сам смысл смотрите. третий элемент 0 и у него есть адрес. т.е. *pa[] = {"dog", "cat", 0}; так я понимаю?
Изображения
 
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
20.06.2019, 15:50
Лучший ответ Сообщение было отмечено alexbmd как решение

Решение

Цитата Сообщение от alexbmd Посмотреть сообщение
но смысл тот-же
Да вот нифига не тот же.

В том посте (а именно в 63) у вас был написан массив указателей.
А сейчас у вас массив массивов (двумерный массив).
Так что я был абсолютно прав, вы нас обманывали и контекст был совсем другой

Если у вас массив указателей, то вы можете использовать нулевой указатель в качестве терминального элемента.
Если у вас двумерный массив, то нет, вы не можете использовать указатель (просто потому, что указатель - это не массив). И в таком случае, да, вы можете использовать пустую строку для обозначения терминального элемента.
При этом, способ проверки дошли ли вы до конца будет отличаться. Об этом уже выше говорили. Для массива указателей с нулевым указателем в качестве терминального элемента вы должны проверять значения указателей в этом массиве. Так было сделано у вас в примере поста #63 (если там исправить "\0" на NULL или 0). Для двумерного массива, в случае терминального элемента представленного пустой строкой, вы должны проверять первый по счету элемент каждого подмассива, как это сделать вам показали в ответах #65 и #70. Да, в случае использования массива указателей вы также можете использовать пустую строку в качестве терминального элемента, т.к. массив приводятся к указателю неявно. Но тогдапроверять вы должны уже не указатели, а первый по счету элемент доступный по каждому указателю в массиве (так же, как в случае подмассива).

Добавлено через 7 минут
Цитата Сообщение от alexbmd Посмотреть сообщение
в случае списка ссылок, обезательно указывать дополнительный терминирующий элемент ?
Списка указателей, ссылок тут нет.
Да, обязательно указывать.

Цитата Сообщение от alexbmd Посмотреть сообщение
тезис 5.0: для списка ссылок, терминирующий элемент как 0 так правильно ?
Правильно.

Цитата Сообщение от alexbmd Посмотреть сообщение
тезис 5.1: этот 0 получается самим адресом ? но почему он получается самим адресом а не значением ?
Да, здесь ноль - это адрес. И все остальные элементы - это тоже адреса. Каждый из трех массивов "dog", "mouse" и "cat" при инициализации pa неявно привелись к указателям и дали адреса, которымм и были проинициализированы элементы pa, наравне с последним элементом-нулем.
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
20.06.2019, 16:32  [ТС]
(массив)список указателей конечно . опечатка сори. поинтеры.

Цитата Сообщение от DrOffset Посмотреть сообщение
А сейчас у вас массив массивов (двумерный массив).
я не придераюсь но вроде сейчас я только говорю про *pa[] что является списком поинтера а не массив массивов ?

самму идею я понял спасибо. значит все тезисы я правильно представил - всё имено так.

Цитата Сообщение от DrOffset Посмотреть сообщение
при инициализации pa неявно привелись к указателям и дали адреса
посмотритре пожалуйста табличку мою цветну. ведь именно так распологается в памяти массив поинтеров. да?
то что там есть имена ele1,ele2 это частный случай . мы же можем объявить *pa[]={ele1,ele2}; а можем *pa[]={"dog"."cat"};
но даже если как второй вариант всеравно строки распологаются в памяти , имеют свои адреса. а *pa[] состоит из начального адреса каждой строки. так ?

получается разместит ли компилятор массив как данные или посчитает этот элемент адрессом на это влияют кавычки а не само появление массива после запятой ?
{"dog","cat","pig"} у всех есть кавычки значит все массивы данные
{"dog","cat", 0} нет кавычек значит будет адрес. да но любой адрес не позволяет присвоить. только нулевой.
правильно я понимаю ?

вообще компилятор там ждет const char", если пишу адрес из памяти дает ошибку
error: invalid conversion from ‘long int’ to ‘const char*’
получается он либо воспринимает "some string" либо 0. но почему на ноль не даешь ошибку как выше. или в компиляторе есть какоето условие что кроме const char* можно только 0 указывать ?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
20.06.2019, 16:44
Цитата Сообщение от alexbmd Посмотреть сообщение
*pa[] состоит из начального адреса каждой строки. так ?
Это верно.

Цитата Сообщение от alexbmd Посмотреть сообщение
получается разместит ли компилятор массив как данные или посчитает этот элемент адрессом на это влияют кавычки а не само появление массива ?
Влияет объявление. Массив указателей или массив массивов.

Цитата Сообщение от alexbmd Посмотреть сообщение
есть какоето условие что кроме const char* можно только 0 указывать ?
Конечно есть. Это же азы языка.

Добавлено через 1 минуту
Цитата Сообщение от alexbmd Посмотреть сообщение
{"dog","cat","pig"} у всех есть кавычки значит все массивы данные
Если объявлено как массив указателей, значит инициализироваться будет указателями. Массивы приведутся к указателям в этом выражении .
Если объявлено как массив массивов, то инициализироваться будет значениями этих строк, т.е. в каждый из подмассивов будет скопировано содержимое этих строк соответственно.
Термин "строка" равно "массив" в данном случае. Т.к. С-style строка - это массив сивмволов. Литеральная строка имеет тип константного массива символов со статическим размещением.
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
20.06.2019, 17:03  [ТС]
с массивом массивов тут всё понятно речи не идёт

я говорил тут про *[]
получается разместит ли компилятор массив как данные или посчитает этот элемент адрессом на это влияют кавычки а не само появление массива после запятой ?
*pa[] = {"dog","cat","pig"} у всех есть кавычки значит все массивы данные
*pa[] = {"dog","cat", 0} нет кавычек значит будет адрес.
ну вообщем я понял , либо стринговые литералы либо ноль. ничего другого туда нельзя запихнуть. причём на ноль особое условие которое конвертирует его в адрес.

запихнул сейчас такое
C++
1
2
int x = 100;
const char *pa[] = {"dog", "mouse", "cat", &(char&)x, 0};
спасибо вам болльшое
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
20.06.2019, 17:34
Цитата Сообщение от alexbmd Посмотреть сообщение
C++
1
&(char&)x
Оптимистично.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
20.06.2019, 17:36
Цитата Сообщение от alexbmd Посмотреть сообщение
причём на ноль особое условие которое конвертирует его в адрес
Запихнуть можно любое число, просто разыменовывать такой адрес нельзя. И ноль в том числе разыменовывать нельзя. Просто его (ноль) часто для удобства и используют, чтобы показать что указатель указывает вникуда. Потому что адрес очередной переменной может случайно совпасть с каким угодно другим адресом.

Добавлено через 2 минуты
Цитата Сообщение от alexbmd Посмотреть сообщение
&(char&)x
C
1
(const char *)(&x)
C++
1
reinterpret_cast<const char *>(&x)
А вообще
C++
1
char x[4] = "100";
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
20.06.2019, 21:32  [ТС]
там в 100 спрятал букву d как и тут (const char *)(&x)

а
C++
1
char x[4] = "100";
просто стринг 100 , но я понял. спасибо.

чтото я туплю,
C++
1
2
3
const char * dog = "dog";
const char * cat = "cat";
const char **pp =
как в pp засунуть dog cat

можно так
C++
1
2
const char * pa[] = {dog,cat};
pp = pa;
но как сразу запихнуть ?

Добавлено через 1 час 15 минут
Как указатели dog cat запихнуть в pp, без посредников?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
20.06.2019, 21:51
Цитата Сообщение от alexbmd Посмотреть сообщение
Как указатели dog cat запихнуть в pp, без посредников?
C++
1
char** pp = new char*[2]{ new char[4]{"cat"}, new char[4]{"dog"} }; // не забыть освободить память
Добавлено через 3 минуты
ну или
C++
1
2
3
    const char * dog = "dog";
    const char * cat = "cat";
    const char** pp = new const char*[2]{ dog, cat };
1
 Аватар для alexbmd
61 / 5 / 1
Регистрация: 03.06.2013
Сообщений: 355
Записей в блоге: 3
21.06.2019, 13:05  [ТС]
друзья, почему если поинтер содержит адресс и мы прыгаем на следующий адресс то разница между ними уже 8 байт и это понятно но если попытаться принт эту разницу то буде 1 а не 8 ?

C++
1
2
3
4
*p
*pp=p
pp++
print pp-p //будет 1 но на самом деле между ними разница же 8. как распечатать 8 а не 1?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.06.2019, 13:05

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
сукцессия 24. Промежуточное общее описание модели
anaschu 12.07.2026
Хендофф: модель АМ→ЭКМ сукцессии микоризы (ризосфера, 50 лет) Содержание проекта Симуляция вековой (50 лет) экологической сукцессии в почве леса Основные участники: АМ-гриб, ЭКМ-гриб,. . .
сукцессия 23. Более физиологичная физиология, более экологичная экология, более диффурные диффуры.
anaschu 12.07.2026
Что реально нашли и починили за эти 5 часов Правило Линдемана (КПД конверсии сахара в тело, kEff) — раньше 100% полученного углерода шло прямо в биомассу гриба; теперь только kEff=0. 5 (после. . .
сукцессия 22. От артефактов к физиологии: калибровка агентной модели грибной сукцессии для воспроизведения сезонной динамики и pH-плато
anaschu 11.07.2026
Аннотация В данной работе представлена калибровка агентной модели динамики грибных сообществ (fungal-succession), направленная на устранение нефизичных артефактов (коллапс биомассы, мгновенное. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru