powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Прошу помочь новичку в С понять указатели и ссылки
15 сообщений из 15, страница 1 из 1
Прошу помочь новичку в С понять указатели и ссылки
    #39617837
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приветствую всех.

Пытаюсь сделать на Ардуине одну вещь. У меня есть структура такого типа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
struct datetime
{
  uint8_t hour;
  uint8_t minute;
  uint8_t second;
  uint8_t day;
  uint8_t month;
  uint16_t year;
  uint8_t weekday;
};



и несколько методов работы с ней:
Код: sql
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.
static void copyDateTime (datetime src, datetime *dest)
{
  dest->hour = src.hour;
  dest->minute = src.minute;
  dest->second = src.second;
  dest->day = src.day;
  dest->month = src.month;
  dest->year = src.year;
  dest->weekday = src.weekday;
};

static uint32_t dtToUnixTime (datetime src)
{
  uint32_t days=0;
  for (uint16_t i=1970; i<src.year; ++i)
   {
    days+=365;
    if (isLeapYear(i)) days++;
   }
  for (uint8_t i=1; i<src.month; ++i)
   {
    days+=DAYSINMONTH [i]; 
    if (i==2) if (isLeapYear(src.year)) days++;
   }
  days+=(src.day-1);
  uint32_t utim = days*SECONDSINDAY;
  utim += (src.hour*SECONDSINHOUR);
  utim += (src.minute*60);
  utim += src.second;
  return utim;
};

static void unixTimeToDT (uint32_t ut, datetime *res)
{ 
  uint16_t year;
  uint8_t month, monthLength;
  uint32_t tim;
  uint32_t days;
  tim=ut;
  res->second=tim%60;
  tim/=60;
  res->minute=tim%60;
  tim/=60;
  res->hour=tim%24;
  tim/=24;
  res->weekday=(tim+4)%7;
  if (res->weekday==0) res->weekday=7;
  year=1970;  
  days=0;
  while ((days+=(isLeapYear(year)?366:365))<=tim) year++;
  res->year=year;
  days-=isLeapYear(year)?366:365;
  tim-=days;
  days=0;
  month=0;
  monthLength=0;
  for (month=1; month<13; month++)
   {
    monthLength=DAYSINMONTH[month];
    if (month==2) if (isLeapYear(year)) monthLength++;         
    if (tim>=monthLength) tim-=monthLength; else break;
   }
  res->month=month;
  res->day = tim+1;  
};

void addSeconds (datetime dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (&dt);
  ut += cnt;
  unixTimeToDT (ut, &dt);
 }



Чтобы добавить к значению datetime несколько секунд, используется метод addSeconds. Однако на выходе у меня остается старое значение. Чую, что намудрил с указателями, но не пойму где именно. Никак не пойму, как правильно объявить и вызывать метод addSeconds, чтобы переменная dt стала указателем на переменную, которую надо поменять. Вот тестовый код:
Код: sql
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.
String dtToString (datetime dt)
{
 String s = "";
 if (dt.day<10) s = s + "0";
 s = s + dt.day;
 s = s + ".";
 if (dt.month<10) s = s + "0";
 s = s + dt.month;
 s = s + ".";
 s = s + dt.year;
 s = s + " ";
 if (dt.hour<10) s = s + "0";
 s = s + dt.hour;
 s = s + ":";
 if (dt.minute<10) s = s + "0";
 s = s + dt.minute;
 s = s + ":";
 if (dt.second<10) s = s + "0";
 s = s + dt.second;
 return s;
}
...
void loop()
 {
  datetime _currentdt;
  _currentdt.day = 20;
  _currentdt.month = 3;
  _currentdt.year = 2018;
  _currentdt.hour = 17;
  _currentdt.minute = 0;
  _currentdt.second = 0;
  Serial.println(dtToString(_currentdt));
  addSeconds(&_currentdt, 4);  
  Serial.println(dtToString(_currentdt));
  while (1 == 1) {};
 }


Заранее благодарен.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39617842
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛюбезныйНикак не пойму, как правильно объявить и вызывать метод addSeconds, чтобы переменная dt
стала указателем на переменную, которую надо поменять.

Или "datetime* dt" или "datetime& dt" - выбирай на вкус.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39617845
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема в том, что внутри этого метода addSeconds есть вызов другого метода, принимающего указатель на datetime. Получается передача указателя в указатель, и компилятор не хочет это пропускать.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39617895
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любезныйи компилятор не хочет это пропускать.
а так?
Код: plaintext
1.
2.
3.
void addSeconds (datetime* dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (dt);


или так?
Код: plaintext
1.
2.
3.
void addSeconds (datetime& dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (&dt);



вообще, если так
Код: plaintext
1.
void addSeconds (datetime dt, uint16_t cnt)

то это означает, что при вызове функции addSeconds будет создан новый объект datetime, в который скопируется передаваемый параметр, работа внутри будет вестись с этим объектом, а не с передаваемым параметром, поэтому значение после выхода не меняется. Ну и плюс ещё будет вызван конструктор. Т.е. передавать сложные объекты таким образом в функции бывает накладно.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39617981
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЛюбезныйПроблема в том, что внутри этого метода addSeconds есть вызов другого метода, принимающего указатель на datetime. Получается передача указателя в указатель, и компилятор не хочет это пропускать.

Чтобы переданная в функцию переменная меняла свое значение после завершения функции надо передать в нее либо ссылку, либо указатель. Первое является по сути константным указателем, поэтому если нет желания "перенаправить" внутри вызываемой функции указатель на другое место, то лучше использовать ссылки (чтобы компилятор мог сделать оптимизации + меньше потенциальных ошибок).

Поэтому надо так (формальный параметр dt становится ссылкой на переменную вызывающей функции):
Код: plaintext
1.
2.
3.
4.
5.
6.
void addSeconds (datetime& dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (dt);
  ut += cnt;
  unixTimeToDT (ut, dt);
 }



"Внутренние" функции должны выглядеть похожим образом (src и res являются ссылкой на первую ссылку, которая является ссылкой на реальную переменную -> src и res является ссылкой на реальную переменную):
Код: plaintext
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.
static uint32_t dtToUnixTime (datetime& src)
{
  uint32_t days=0;
  for (uint16_t i=1970; i<src.year; ++i)
   {
    days+=365;
    if (isLeapYear(i)) days++;
   }
  for (uint8_t i=1; i<src.month; ++i)
   {
    days+=DAYSINMONTH [i]; 
    if (i==2) if (isLeapYear(src.year)) days++;
   }
  days+=(src.day-1);
  uint32_t utim = days*SECONDSINDAY;
  utim += (src.hour*SECONDSINHOUR);
  utim += (src.minute*60);
  utim += src.second;
  return utim;
};

static void unixTimeToDT (uint32_t ut, datetime& res)
{ 
  uint16_t year;
  uint8_t month, monthLength;
  uint32_t tim;
  uint32_t days;
  tim=ut;
  res.second=tim%60;
  tim/=60;
  res.minute=tim%60;
  tim/=60;
  res.hour=tim%24;
  tim/=24;
  res.weekday=(tim+4)%7;
  if (res.weekday==0) res.weekday=7;
  year=1970;  
  days=0;
  while ((days+=(isLeapYear(year)?366:365))<=tim) year++;
  res.year=year;
  days-=isLeapYear(year)?366:365;
  tim-=days;
  days=0;
  month=0;
  monthLength=0;
  for (month=1; month<13; month++)
   {
    monthLength=DAYSINMONTH[month];
    if (month==2) if (isLeapYear(year)) monthLength++;         
    if (tim>=monthLength) tim-=monthLength; else break;
   }
  res.month=month;
  res.day = tim+1;  
};



Смысл твое чудо- кода я не анализировал, только изменил правильность работы с ссылками.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618071
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любезный,

boost::datetime же...
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618074
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любезный,

Код: plaintext
1.
2.
3.
4.
5.
6.
void addSeconds (datetime dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (&dt);
  ut += cnt;
  unixTimeToDT (ut, &dt);
 }



Ты видимо модифицируешь переменную dt , а передаёшь то ты её в функцию ПО ЗНАЧЕНИЮ,
это значение в функции и умирает..

Не майся дурью , используй boost::datetime.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618075
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛюбезныйПроблема в том, что внутри этого метода addSeconds есть вызов другого метода, принимающего указатель на datetime. Получается передача указателя в указатель, и компилятор не хочет это пропускать.

Не ну это тебе книжки надо читать.
Так мы тебе каждую строчку твоего кода писать будем.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618253
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivЛюбезный,

boost::datetime же...
Буст в ардуине? Не смешите.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618444
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автора так?

Код: sql
1.
2.
3.
void addSeconds (datetime* dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (dt);



авторexit status 1
could not convert 'dt' from 'datetime*' to 'datetime'

авторили так?

Код: sql
1.
2.
3.
void addSeconds (datetime& dt, uint16_t cnt)
 {
  uint32_t ut = dtToUnixTime (&dt);


авторexit status 1
could not convert '& dt' from 'datetime*' to 'datetime'

авторто это означает, что при вызове функции addSeconds будет создан новый объект datetime, в который скопируется передаваемый параметр, работа внутри будет вестись с этим объектом, а не с передаваемым параметром, поэтому значение после выхода не меняется. Ну и плюс ещё будет вызван конструктор. Т.е. передавать сложные объекты таким образом в функции бывает накладно.
Всем большое спасибо за подсказки. То, что у меня идет передача по значению мне было понятно и ранее, однако у меня просто не шибко укладывается в голове, как организовать внутри метода, принимающего в качестве входного параметра указатель на переменную, вызов другого метода, принимающего тот же самый указатель для корректировки значения переменной. Была бы возможность явно указать, что я перекидываю адрес переменной в памяти из одного метода в другой... Надо мне слегка отоспаться после дежурства, может быть, завтра удастся что-то попробовать в среде с компиляцией и проверкой результата на плате. Бусты - не знаю, как Ардуино может их воспринять. Хочу все же сделать что-то простенькое и попутно понять арифметику и записи указателей в Си-подобных языках. Книжку читаю, нашел там про передачу ссылки на структуру и про запись вида res->day, здесь как раз понятно. А про передачу указателя из метода в метод - как-то не прет, может быть, книжка объясняет не шибко ясно.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618448
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Буст не трогай, это нехороший совет был. Если в С++ с трудом разбираешься, то буст тебе мозг взорвет.

А с указателями все просто, указатель это адрес в памяти где лежит данные заданного типа.

Сами данные
Код: plaintext
1.
type a;


адрес этих данных
Код: plaintext
1.
&a


Указатель
Код: plaintext
1.
type *p = &a;


Получение данных по указателю
Код: plaintext
1.
type b = *p;


Но лучше указателями лишний раз не пользоваться, стрелять в ноги с ними проще простого.

Используй ссылки
Код: plaintext
1.
2.
3.
void f(type& a) {
   a....
}


Просто добавил & после типа и в функцию передается не копия переменной, а используется сама переменная.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618467
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любезныйу меня просто не шибко укладывается в голове, как организовать внутри метода, принимающего
в качестве входного параметра указатель на переменную, вызов другого метода, принимающего
тот же самый указатель

После того, как ты получаешь указатель на вход - можешь засовывать этот указатель куда
угодно и сколько угодно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618713
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторБуст не трогай, это нехороший совет был. Если в С++ с трудом разбираешься, то буст тебе мозг взорвет.
А с указателями все просто, указатель это адрес в памяти где лежит данные заданного типа.
За этот пост отдельное спасибо: всё коротко, ёмко и ясно в одном сообщении. В книжке, которую я смотрю, всё это разбито на несколько страниц, и у меня это как-то не компоновалось.

авторНо лучше указателями лишний раз не пользоваться, стрелять в ноги с ними проще простого.
Используй ссылки
Конкретно в данном случае я решил сделать через ссылки, и всё заработало. Но к сожалению, насколько я понял, ссылки - это прерогатива плюсового языка, а так как я потом хочу научиться программировать микроконтроллеры на чистом С, от указателей никуда не уйти. Впрочем, я предпочитаю стрелять сразу в голову. :) Разберусь, тем более в этой теме уже написано достаточно всего. Всем огромное спасибо.
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39618846
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛюбезныйавторБуст не трогай, это нехороший совет был. Если в С++ с трудом разбираешься, то буст тебе мозг взорвет.
А с указателями все просто, указатель это адрес в памяти где лежит данные заданного типа.
За этот пост отдельное спасибо: всё коротко, ёмко и ясно в одном сообщении. В книжке, которую я смотрю, всё это разбито на несколько страниц, и у меня это как-то не компоновалось.

авторНо лучше указателями лишний раз не пользоваться, стрелять в ноги с ними проще простого.
Используй ссылки
Конкретно в данном случае я решил сделать через ссылки, и всё заработало. Но к сожалению, насколько я понял, ссылки - это прерогатива плюсового языка, а так как я потом хочу научиться программировать микроконтроллеры на чистом С, от указателей никуда не уйти. Впрочем, я предпочитаю стрелять сразу в голову. :) Разберусь, тем более в этой теме уже написано достаточно всего. Всем огромное спасибо.

Вообще, что написано тут, написано в любой книжке (по С или С++).
Почему бы тебе их не почитать?
...
Рейтинг: 0 / 0
Прошу помочь новичку в С понять указатели и ссылки
    #39619630
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Значит, не ту книшку читал. Там тоже это написано, однако разнесено так, что без стакана не разберёшься, особенно в условиях работы с проектом.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Прошу помочь новичку в С понять указатели и ссылки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]