简体   繁体   中英

Can someone please explain me this Pointer usage?

I am learning how to code for ARM A9 under Linux. Right now I access some peripherals like LEDS. My code is actually working, but partly based on a tutorial. The only one part I don't understand is:

  void *virtual_base;
  void *led_addr;
  void *sw_addr;
  int fd;
  int switches;
  switches=*(uint32_t *)sw_addr;

`

The part I don't understand is why do I have to write *(uint32_t *)sw_addr;

*sw_addr means it is a variable, which points to a specific address.In my case it points to specific peripheral register.Reading from this address will read the status of switches on my board. But what

*(uint32_t *)sw_addr means? How do you interpret it? Why I just cant write switches= sw_addr ?

I am bit confused , as you can see.

sw_addr is a void pointer. void pointers cannot be dereferenced, because void is the no-type type, ie there is no such thing as void a; as variable declaration. Therefore the pointer is cast to a uint32_t* , before it is dereferenced. The value at the address of sw_addr is now interpreted as an `uint32_t, when it is dereferenced.

Edit: I should mention that the specific operation in your code might not be safe, because you are assigning the result to an int (which is signed, whereas the u in uint32_t stands for unsigned). An int may not be able to represent the number stored in a uint32_t , first because unsigned int s can store larger numbers, but possibly also because an int is not guaranteed to be 32 bits large.

Let's break it down into steps:

  1. sw_addr is a variable. The value of the variable is X .
  2. In the memory, at address X sits some 32 bit (4 bytes) value that you want to read into the variable "switches".
  3. *sw_addr means "the value at address X", meaning the value that we want to read into "switches".
  4. Since sw_addr is of type void * , we can't write switches = *sw_addr; since the compiler doesn't know the size of the data that you want to read. Maybe you're trying to read only one byte, maybe two bytes, maybe four?
  5. The casting (uint32_t *)sw_addr tells the compiler to look at sw_addr as if it were a pointer to a uint32_t , meaning a pointer to an unsigned 32 bit value.
  6. The statement *((uint32_t *)sw_addr); (i've added another pair of brackets for clarity, but it doesn't matter) means the value pointed by our (uint32_t *)sw_addr pointer ie the 4 byte unsigned value at address X.
  7. With the casting in place, we can write switches=*(uint32_t *)sw_addr; and it's clear that we intend to read 4 bytes from address X into switches .

Alternatively, we could have written the following:

uint32_t *sw_addr;
int switches;

switches=*sw_addr;

The "for dummies" answer:

*(uint32_t *)sw_addr means?

It means, give me uint32_t worth of data (32 bits) from where sw_addr points to.

How do you interpret it?

void *sw_addr points to something of unknown size, it's a void pointer . Casting it to a uint32_t pointer tells us it points to a 32bit unsigned integer . Then when we want the data, we get 32 bits (assuming all casts are correct and can be made).

Why I just cant write switches= sw_addr?

Assuming you mean switches = *sw_addr , it's because it's like saying: Give me unknown amount of data from pointer sw_addr (we don't know the type its pointing too).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM