Перейти к содержанию
    

Указатели на переменные.

Может кто-то найти время и доступным языком написать что такое указатели в С?

Логично, что сначала надо идти в гугл читать. Но есть куча статей, что это такое. Ну как бы понятно, указатель на переменную, на ее адрес бла бла. А зачем ?? Когда можно просто изменить переменную и она изменится ВЕЗДЕ.

 

https://medium.com/nuances-of-programming/для-чего-нужен-указатель-в-язык-си-4e048cac4755  Вот статья, пишут :

// Эта функция не будет работать, так как в Си функция передаётся по значению.
// Внесённые изменения не действительны за пределами функции.
void increment(int i) {
   i = i + 1;
}

функция не будет работать. Вставляю в проект, запускаю дебаг. Все работает. Переменная меняется. Помогите. Если можно с примером.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, Denis_N сказал:

Может кто-то найти время и доступным языком написать что такое указатели в С?

Ну ежли доступным: указатель на объект, это собственно адрес объекта в памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 minutes ago, Denis_N said:

 


// Эта функция не будет работать, так как в Си функция передаётся по значению.
// Внесённые изменения не действительны за пределами функции.
void increment(int i) {
   i = i + 1;
}

Вставляю в проект, запускаю дебаг. Все работает. Переменная меняется. Помогите. Если можно с примером.

Так вы в какой точке смотрите состояние переменной и наблюдаете изменение, непосредственно внутри функции или снаружи?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, alexunder сказал:

Так вы в какой точке смотрите состояние переменной и наблюдаете изменение, непосредственно внутри функции или снаружи?

Снаружи.

char increment(char t)
{
	t = t + 1;	 
	return t;
}
inc = increment(5);

Так вот inc = 6. нет проблем...зачем городить указатели?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 поменяется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, Denis_N said:

А зачем ?? Когда можно просто изменить переменную и она изменится ВЕЗДЕ.

А как Вы её измените? Если это переменная, к примеру, автоматическая - т.е. выделенная на стеке текущей функции. И Вы в этой функции вызываете другую функцию, которая Вам должна эту переменную поменять. Без указателя это сделать невозможно. Также через указатели можно обращаться к регистрам ввода-вывода, по-другому никак. Переменные часто принято прятать, а не выставлять напоказ - т.е. не делать глобальными. В этом случае лучше передать на неё адрес, т.к. по-другому доступ к ней тоже получить сложно. Далее, Вам может понадобиться получить доступ к некому диапазону памяти, в этом случае тоже удобнее использовать указатель, инкрементируя или декрементируя его значение (адрес). И это далеко не все примеры использования указателей. Поверьте, без них очень сложно в Си/Си++)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

// Эта функция не будет работать, так как в Си функция передаётся по значению.
// Внесённые изменения не действительны за пределами функции.
void increment(int i)
{
  i = i + 1;
}

 

8 часов назад, Denis_N сказал:

Все работает. Переменная меняется. Помогите. Если можно с примером.

Вот вам пример. Проверяйте:

int a = 5;
// Чему равно а?
increment(a);
// Чему равно а сейчас?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, Denis_N said:

Все работает. Переменная меняется.

Внутри функции будет меняться, ведь это локальная переменная.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 сказал:

А как Вы её измените? Если это переменная, к примеру, автоматическая - т.е. выделенная на стеке текущей функции. И Вы в этой функции вызываете другую функцию, которая Вам должна эту переменную поменять. Без указателя это сделать невозможно.

И здесь Вы неправы. Возможно. Обновите свои знания си++.  :wink:

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

 

Как видно: меняем значение локальной переменной вызывающей функции в вызываемой. И при этом прекрасно обходимся без указателей.  :unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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:

И здесь Вы неправы. Возможно. Обновите свои знания си++.  :wink:

Речь вообще-то шла про Си.

Да и ссылка это разновидность указателя.

15 hours ago, Denis_N said:

Может кто-то найти время и доступным языком написать что такое указатели в С?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, dimka76 сказал:

Кошмар. Ни о какой переносимости и речи нет )))

Это претензии уже к создателям МК. Они, бездельники, :punish: почему-то до сих пор не договорились чтобы приферию унифицировать.  

7 минут назад, dimka76 сказал:

Речь вообще-то шла про Си.

А вы почитайте тот пост, на который я отвечал. Там речь про си++.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, jcxz said:

Это претензии уже к создателям МК. Они, бездельники, :punish: почему-то до сих пор не договорились чтобы приферию унифицировать.  

Я не про это, а про кучу компиляторозависимых ключевых слов в вашем примере.

Вот, все универсально

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)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, dimka76 сказал:

Я не про это, а про кучу компиляторозависимых ключевых слов в вашем примере.

Вот, все универсально

Ну да, а теперь введите это "универсальное" в окошко Watch IAR и посмотрите куда он вас пошлёт.

А с моим вариантом нормально показывает значения регистров в/в. А мне важнее "ехать" чем "шашечки".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, jcxz said:

А вы почитайте тот пост, на который я отвечал. Там речь про си++.

А при чём тут Си++ Я про Си говорил...

2 hours ago, jcxz said:

Не совсем корректное утверждение.

Ну и ладно, быть везде правым невозможно да и не нужно)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...