简体   繁体   中英

How to pass an array pointer to a function?

I have two arrays. And I am calling a function inside main in which I am updating one of the arrays according to some of the values in the other array.

volatile float32_t raw_data[3]; //this is being updated by an interrupt handler
void get_acc(int32_t* acc_data, float32_t* raw_data)
{
  acc_data[0] = (raw_data[0] - OFFSETX)/SENSX; //OFFSETX and SENSX defined as a macro
  acc_data[1] = (raw_data[1] - OFFSETY)/SENSY;
  acc_data[2] = (raw_data[2] - OFFSETZ)/SENSZ;
}
int main()
{
  int32_t acc_data[3];      
  int32_t data_ready = 0;  //being updated by interrupt handler
  while(1)
  {
  if(data_ready)
  get_acc(acc_data,raw_data);
  }
}

To my absolute shock, when I watch the variables using breakpoints and stepping through get_acc, only the first one acc_data[0] gets updated, all others are set to 0 even though they are executed. Now my first suspicion is it is something related to pointer, probably the address not being updated properly. Because I have used passing arrays to function like that where I updated the array indexes inside a for loop, not manually. Can anybody give an insight what might be wrong.

You probably have subtle synchronization errors here:

  1. As Jonathan pointed out raw_data has lost its qualifier inside the function. Using a volatile variable in such a way is undefined behavior, even if there is no signal handler involved.
  2. It seems in addition that your data is touched asynchronously by a signal handler. The only data type as of C99 that you may touch with such a signal handler is sig_atomic_t . C11 goes a bit further and also allows for other lock free atomic types:

When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects that are neither lock-free atomic objects nor of type volatile sig_atomic_t are unspecified, as is the state of the floating-point environment. The value of any object modified by the handler that is neither a lock-free atomic object nor of type volatile sig_atomic_t becomes indeterminate when the handler exits, as does the state of the floating-point environment if it is modified by the handler and not restored to its original state.

As you see, especially touching floating points is considered a no go.

When compiled the code (GCC 4.7.1 on Mac OS X 10.7.5), I get a warning:

warning: passing argument 2 of ‘get_acc’ discards ‘volatile’ qualifier from pointer target type [enabled by default]
note: expected ‘float32_t *’ but argument is of type ‘volatile float32_t *’

I'm not sure that this accounts for your trouble, but it might be a factor. I note that data_ready should also be volatile qualified.

Also, if you compile with -Wshadow , you get:

In function ‘get_acc’:
warning: declaration of ‘raw_data’ shadows a global declaration [-Wshadow]

This is more a 'risk of misunderstanding' issue than anything more serious.

However, apart from the difference in qualifiers, the code you show is clean and the compiler should be generating code to read three values from raw_data and processing those into acc_data . Have you looked at the assembly language generated for the function?

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