Arrow operator -> and (x*var).y

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anyone can explain what these code do? what does the -> means and what similarity to (x*var).y ?

 

for (int i = 0; i < 1000; i+=3)
{
  htim14.Instance->CCR1 = i;
  HAL_Delay(1);
}
for (int i = 1000; i > 0; i-=3)
{
  htim14.Instance->CCR1 = i;
  HAL_Delay(1);
}

Edinburgh

Last Edited: Thu. Sep 9, 2021 - 06:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

What - Don't people google* stuff for themselves anymore ?

 

A search for "arrow operator in C" returns some 41 million results, so there's not a shortage of information on this. We really don't need to add more on this subject.

 

(*) Other Internet Search Engines are available.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hmsEdinburgh wrote:
what does the -> means

What does your C textbook tell you?

 

Or an internet search for "C operators" ?

 

Here's some C learning and reference materials - including a free online textbook:

 

https://blog.antronics.co.uk/2011/08/08/so-youre-thinking-of-starting-with-c/

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Sep 9, 2021 - 07:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's struct dereference. If you have:

typedef struct {
    int n;
    long l;
} mystr_t;

mystr_t foo;

void initStruct(mystr_t * pStr) {
    pStr->n = 123;
    pStr->l = 0xBABEFACE;
}

int main(void) {
    iniStruct( &foo );
}

Then when main() starts it calls initStruct and passes it the ADDRESS OF the foo struct in memory. When it arrives in to the initStruct() function it can't just do:

pStr.n = 123;
pStr.l = 0xBABEFACE;

because pStr itself is not a structure. It is the address of a structure. So the -> operator is used to say "go to the address this is pointing at and at the offset of the 'n' or 'l' member write this new value".

 

In modern embedded micros (Xmega, ARM) it is increasingly common for there to be multiple instances of peripherals. Perhaps there are four..eight timers that are all the same? So each may have a bank of control registers in memory that looks something like:

typdef struct {
    utin8_t CONTROL;
    uint8_t STATUS;
    uint8_t COUNT;
} timer_t;

then there may be copies of this register block at address 0x40, 0x80, 0xC0, etc so elsewhere there's maybe something like:

#define TIMER0 (*(volatile timer_t)0x40)
#define TIMER1 (*(volatile timer_t)0x80)
#define TIMER2 (*(volatile timer_t)0xc0)
...

so that is three different timers with a set of the same registers but at three different places. Now you might have some simple function like:

void startTimer0() {
    if (TIMER0.STATUS & (READY_TO_START_bit)) {
        TIMER0.CONTROL |= START_TIMER_bit;
    }
}

but suppose you need the same for TIMER1 and TIMER2? You will end up with:

void startTimer1() {
    if (TIMER1.STATUS & (READY_TO_START_bit)) {
        TIMER1.CONTROL |= START_TIMER_bit;
    }
}

void startTimer2() {
    if (TIMER2.STATUS & (READY_TO_START_bit)) {
        TIMER2.CONTROL |= START_TIMER_bit;
    }
}

If there were actually 8 (or more) of these timers imagine how tedious it would get to write and maintain the same code for what are effectively eight+ different copies of the same thing. If you could just pass in the 0x40, 0x80, 0xC0... base address of a chosen timer you might only need one copy of this. Well you can:

void startTimer(timer_t * pTimer) {
    if (pTimer->STATUS & (READY_TO_START_bit)) {
        pTimer->CONTROL |= START_TIMER_bit;
    }
}

This is using that -> struct dereference operator to be able to write to struct members such as STATUS and CONTROL knowing nothing more than the base address of the register block. You might then have:

int main(void) {
    startTimer(&TIMER1);
    startTimer(&TIMER3);
    startTimer(&TIMER6);
}

Each call just passes the base address of different register blocks at different addresses.

 

You will see this pattern/template used a lot in modern embedded micro code. Generic peripheral operation functions that can be used for one of eight timers or one of five UARTs or whatever and they will all have some kind of func_name(peripheral_layout_type * pPeripheral, ...) parameter to which the & (address of) some peripheral (TIMER3, UART4, etc) is passed,

 

In the example you showed:

  htim14.Instance->CCR1 = i;

then the bit to the left of -> is clearly the address of something, in fact it looks like something very similar to "TIMER14" perhaps judging by the slightly confusing name.

 

(Wow does some chip really have 14+ timers ?? ;-)

Last Edited: Thu. Sep 9, 2021 - 08:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hmsEdinburgh wrote:

Anyone can explain what these code do? what does the -> means

 

In modern C `a->b` is equivalent to `(*a).b`. Kindergarten-grade questions like that are better learned from a book.

 

Is your question about C or C++???

 

hmsEdinburgh wrote:

and what similarity to (x*var).y ?

 

Um... What is that supposed to mean?

Dessine-moi un mouton

Last Edited: Thu. Sep 9, 2021 - 02:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndreyT wrote:
In modern C `a->b` is equivalent to `(*a).b`

hmsEdinburgh wrote:

and what similarity to (x*var).y ?

AndreyT wrote:
Um... What is that supposed to mean?

perhaps it was supposed to mean (*var).y ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As usual, that was an awesome example  

CLAWESOME  ...nails a very pertinent application for this operator ...saves, time, space, and maybe sanity

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1


Arrow operator:

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe also a book would help? Look for "Pointers and structures", this one will do:

 

https://gforge.inria.fr/frs/download.php/latestfile/5298/ModernC.pdf

 

on page 140

 

update: add link to book I will keep link to code bellow

 

https://gforge.inria.fr/frs/download.php/latestfile/5298/code.zip

Last Edited: Thu. Sep 9, 2021 - 06:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems you have an stm32-

https://github.com/dekuNukem/STM...

 

In addition to learning the C language which does not happen overnight, you will also need to learn to follow the headers provided to you-

https://godbolt.org/z/WY1Geo9o3

 

this code was relevant parts extracted from stm32g031 headers, which also has a timer14.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, 14+ Timer found in STM32F ARM Cortex-M 

Edinburgh