Denis_N 0 22 ноября, 2021 Опубликовано 22 ноября, 2021 · Жалоба Может кто-то найти время и доступным языком написать что такое указатели в С? Логично, что сначала надо идти в гугл читать. Но есть куча статей, что это такое. Ну как бы понятно, указатель на переменную, на ее адрес бла бла. А зачем ?? Когда можно просто изменить переменную и она изменится ВЕЗДЕ. https://medium.com/nuances-of-programming/для-чего-нужен-указатель-в-язык-си-4e048cac4755 Вот статья, пишут : // Эта функция не будет работать, так как в Си функция передаётся по значению. // Внесённые изменения не действительны за пределами функции. void increment(int i) { i = i + 1; } функция не будет работать. Вставляю в проект, запускаю дебаг. Все работает. Переменная меняется. Помогите. Если можно с примером. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 197 22 ноября, 2021 Опубликовано 22 ноября, 2021 · Жалоба 5 минут назад, Denis_N сказал: Может кто-то найти время и доступным языком написать что такое указатели в С? Ну ежли доступным: указатель на объект, это собственно адрес объекта в памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexunder 4 22 ноября, 2021 Опубликовано 22 ноября, 2021 · Жалоба 11 minutes ago, Denis_N said: // Эта функция не будет работать, так как в Си функция передаётся по значению. // Внесённые изменения не действительны за пределами функции. void increment(int i) { i = i + 1; } Вставляю в проект, запускаю дебаг. Все работает. Переменная меняется. Помогите. Если можно с примером. Так вы в какой точке смотрите состояние переменной и наблюдаете изменение, непосредственно внутри функции или снаружи? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Denis_N 0 22 ноября, 2021 Опубликовано 22 ноября, 2021 · Жалоба 1 минуту назад, alexunder сказал: Так вы в какой точке смотрите состояние переменной и наблюдаете изменение, непосредственно внутри функции или снаружи? Снаружи. char increment(char t) { t = t + 1; return t; } inc = increment(5); Так вот inc = 6. нет проблем...зачем городить указатели? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 43 22 ноября, 2021 Опубликовано 22 ноября, 2021 · Жалоба 10 minutes ago, Denis_N said: Так вот inc = 6. нет проблем...зачем городить указатели? Этот ваш пример и пример из приведенной вами ссылке в первом вашем сообщение это разные примеры. Для чего может быть нужен. 1. В микроконтроллерах имена всех регистров периферии это указатели. 2. Например для передачи больших объектов в функцию struct s_ss{ int a; int b; int c; char cc[100]; }ss; void foo(struct s_ss s1) { } void foo_2(void) { foo(ss); } Здесь при вызове foo() будет происходить копирование всех членов структуры. struct s_ss{ int a; int b; int c; char cc[100]; }ss; void foo(struct s_ss* s1) { } void foo_2(void) { foo(&ss); } Здесь будет передан только адрес структуры, что потребует для передачи аргумента в функции только через один регистр. Ну и опять же struct s_ss{ int a; int b; int c; char cc[100]; }ss; void foo(struct s_ss s1) { s1.a += 10; } void foo_2(void) { foo(ss); } Здесь значение поля а структуры ss не поменяется. struct s_ss{ int a; int b; int c; char cc[100]; }ss; void foo(struct s_ss* s1) { s1->a += 10; } void foo_2(void) { foo(&ss); } Здесь значение поля а структуры ss поменяется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 3 hours ago, Denis_N said: А зачем ?? Когда можно просто изменить переменную и она изменится ВЕЗДЕ. А как Вы её измените? Если это переменная, к примеру, автоматическая - т.е. выделенная на стеке текущей функции. И Вы в этой функции вызываете другую функцию, которая Вам должна эту переменную поменять. Без указателя это сделать невозможно. Также через указатели можно обращаться к регистрам ввода-вывода, по-другому никак. Переменные часто принято прятать, а не выставлять напоказ - т.е. не делать глобальными. В этом случае лучше передать на неё адрес, т.к. по-другому доступ к ней тоже получить сложно. Далее, Вам может понадобиться получить доступ к некому диапазону памяти, в этом случае тоже удобнее использовать указатель, инкрементируя или декрементируя его значение (адрес). И это далеко не все примеры использования указателей. Поверьте, без них очень сложно в Си/Си++) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darth Vader 0 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба // Эта функция не будет работать, так как в Си функция передаётся по значению. // Внесённые изменения не действительны за пределами функции. void increment(int i) { i = i + 1; } 8 часов назад, Denis_N сказал: Все работает. Переменная меняется. Помогите. Если можно с примером. Вот вам пример. Проверяйте: int a = 5; // Чему равно а? increment(a); // Чему равно а сейчас? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 8 hours ago, Denis_N said: Все работает. Переменная меняется. Внутри функции будет меняться, ведь это локальная переменная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 197 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 10 часов назад, haker_fox сказал: Также через указатели можно обращаться к регистрам ввода-вывода, по-другому никак. Не совсем корректное утверждение. У меня, например, регистры в/в описаны типа: //ETHERNET typedef struct { __IO u32 MAC_CONFIGURATION; //MAC Configuration Register __IO u32 MAC_FRAME_FILTER; //MAC Frame Filter ... } HwRegsENET; #ifdef SHARE_C #define EXTERN #else #define EXTERN extern #endif #define HWREG_MAP(id) __no_init __root __absolute HwRegs##id ... EXTERN volatile HWREG_MAP(USIC) USIC2 @ 0x48024000; EXTERN volatile HWREG_MAP(ENET) ENET @ 0x5000C000; EXTERN volatile HWREG_MAP(CAN) CAN @ 0x48014000; EXTERN volatile HWREG_MAP(SDMMC) SDMMC @ 0x4801C000; ... И обращение к ним в коде: ENET.MAC_CONFIGURATION = ...; ENET.MAC_FRAME_FILTER = ...; Как видно - никаких указателей явно не фигурирует. Хотя конечно - при компиляции под ARM, для доступа к ним будет использована косвенная адресация (как будто с указателями). Но так это - особенность платформы. Главное, что си-шных указателей - нет. 10 часов назад, haker_fox сказал: А как Вы её измените? Если это переменная, к примеру, автоматическая - т.е. выделенная на стеке текущей функции. И Вы в этой функции вызываете другую функцию, которая Вам должна эту переменную поменять. Без указателя это сделать невозможно. И здесь Вы неправы. Возможно. Обновите свои знания си++. void f1(uint &ii) { ii++; } void f2() { uint i = 1; f1(i); } Скрытый текст #pragma inline=never In section .text, align 2, keep-with-next void f1(uint &ii) { ii++; _Z2f1Rj: (+1) 00000000 0x6801 LDR R1,[R0, #+0] 00000002 0x1C49 ADDS R1,R1,#+1 00000004 0x6001 STR R1,[R0, #+0] } 00000006 0x4770 BX LR ;; return #pragma inline=never In section .text, align 2, keep-with-next void f2() { _Z2f2v: (+1) 00000000 0xB580 PUSH {R7,LR} uint i = 1; 00000002 0x2001 MOVS R0,#+1 00000004 0x9000 STR R0,[SP, #+0] f1(i); 00000006 0x4668 MOV R0,SP 00000008 0x.... 0x.... BL _Z2f1Rj } 0000000C 0xBD01 POP {R0,PC} ;; return In section .text, align 2, keep-with-next __noreturn void main() { main: (+1) 00000000 0xB082 SUB SP,SP,#+8 f2(); 00000002 0x.... 0x.... BL _Z2f2v Как видно: меняем значение локальной переменной вызывающей функции в вызываемой. И при этом прекрасно обходимся без указателей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 43 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 29 minutes ago, jcxz said: Не совсем корректное утверждение. У меня, например, регистры в/в описаны типа: //ETHERNET typedef struct { __IO u32 MAC_CONFIGURATION; //MAC Configuration Register __IO u32 MAC_FRAME_FILTER; //MAC Frame Filter ... } HwRegsENET; #ifdef SHARE_C #define EXTERN #else #define EXTERN extern #endif #define HWREG_MAP(id) __no_init __root __absolute HwRegs##id ... EXTERN volatile HWREG_MAP(USIC) USIC2 @ 0x48024000; EXTERN volatile HWREG_MAP(ENET) ENET @ 0x5000C000; EXTERN volatile HWREG_MAP(CAN) CAN @ 0x48014000; EXTERN volatile HWREG_MAP(SDMMC) SDMMC @ 0x4801C000; ... Кошмар. Ни о какой переносимости и речи нет ))) 29 minutes ago, jcxz said: И здесь Вы неправы. Возможно. Обновите свои знания си++. Речь вообще-то шла про Си. Да и ссылка это разновидность указателя. 15 hours ago, Denis_N said: Может кто-то найти время и доступным языком написать что такое указатели в С? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 197 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 7 минут назад, dimka76 сказал: Кошмар. Ни о какой переносимости и речи нет ))) Это претензии уже к создателям МК. Они, бездельники, почему-то до сих пор не договорились чтобы приферию унифицировать. 7 минут назад, dimka76 сказал: Речь вообще-то шла про Си. А вы почитайте тот пост, на который я отвечал. Там речь про си++. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 43 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 1 minute ago, jcxz said: Это претензии уже к создателям МК. Они, бездельники, почему-то до сих пор не договорились чтобы приферию унифицировать. Я не про это, а про кучу компиляторозависимых ключевых слов в вашем примере. Вот, все универсально typedef struct { __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ ..... __IO uint32_t OR; /*!< TIM option register, Address offset: 0x50 */ } TIM_TypeDef; #define PERIPH_BASE 0x40000000U /*!< Peripheral base address in the alias region #define APB1PERIPH_BASE PERIPH_BASE #define TIM2_BASE (APB1PERIPH_BASE + 0x0000U) #define TIM2 ((TIM_TypeDef *) TIM2_BASE) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 197 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 6 минут назад, dimka76 сказал: Я не про это, а про кучу компиляторозависимых ключевых слов в вашем примере. Вот, все универсально Ну да, а теперь введите это "универсальное" в окошко Watch IAR и посмотрите куда он вас пошлёт. А с моим вариантом нормально показывает значения регистров в/в. А мне важнее "ехать" чем "шашечки". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Denis_N 0 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба Большое спасибо. Можно закрывать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 23 ноября, 2021 Опубликовано 23 ноября, 2021 · Жалоба 1 hour ago, jcxz said: А вы почитайте тот пост, на который я отвечал. Там речь про си++. А при чём тут Си++ Я про Си говорил... 2 hours ago, jcxz said: Не совсем корректное утверждение. Ну и ладно, быть везде правым невозможно да и не нужно) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться