简体   繁体   中英

Passing a pointer to a function doesn't change its value

I'm facing a weird behavior. My C knowledge isn't enough to understand what's happening.

I'm using TI's C compiler (for CC3220SF) in Code Composer Studio. As I did usually I wrote this function:

unsigned char rxBuf[512];

void ReadID(unsigned char device[])
{
    // this function reads 2 bytes and put them into
    // the global buffer rxBuf;
    FlashMemory_Read(ID_ADDRESS, 2);
    device = &rxBuf[0];
}

(Note: here I don't pass the length because it's fixed to 2 by design).

Here how I use it:

unsigned char device[2];   
ReadID(device);

as pointed out from many answers the compiler treats in the same way a parameter declared as * or [], and its value is the address (pointer) to the first element.

Two unexpected behaviors:

  1. the compiler warns me that in the ReadID function the 'device' variable was declared but never referenced
  2. debugging the code, I noticed that inside the ReadID function the device bytes point to the rxBuf values, but in the function that calls ReadID() they read always 0.

What is wrong here, and why?

The expected behavior is the device variable should point to rxBuf even when ReadID ends, because the pointer has set to the address of rxBuf. Instead it seems the address is changed only locally!

Your problem is similar to this FAQ: Dynamic memory access only works inside function .

Since the array device[] decays into unsigned char* device when passed as parameter, you end up with a pointer device which is local to that function . Assigning that local copy to point somewhere means it would only last for as long as you are inside the function.

But since what you have in the caller is an array, and not a pointer, this suggests that you have completely misunderstood how arrays and pointers work. Best advice is to re-read those chapters in your C programming book.

What you actually meant to do was probably something like this instead:

void ReadID(unsigned char device[])
{
  FlashMemory_Read(ID_ADDRESS, 2);
  device[0] = rxBuf[0];
  device[1] = rxBuf[1];
}

As a side note, having a global variable of 512 bytes that various functions write to, is horrible program design. Proper design would be to have a function along the lines of this instead:

void FlashMemory_Read(volatile const uint8_t* address, 
                      size_t size, 
                      uint8_t dstbuf[size]);

You are only changing where device points to locally.

What you want to do is something along the line:

void ReadID(unsigned char device[])
{
    // this function reads 2 bytes and put them into
    // the global buffer rxBuf;
    FlashMemory_Read(ID_ADDRESS, 2);
    memcpy(device, rxBuf, 2);
}

Also note that rxBuf and &rxBuf[0] points to the exact same address in memory.

the compiler warns me that in the ReadID function the 'device' variable was declared but never referenced

The value of the parameter device is not used in the function, Thus the parameter does not make sense.

Take into account that function parameters are its local variables.

debugging the code, I noticed that inside the ReadID function the device bytes point to the rxBuf values, but in the function that calls ReadID() they read always 0.

What you are trying to do is to change an array but arrays are not modifiable lvalues. When a variable of an array type is declared it can not change its type and denote a different array.

In this call

unsigned char device[2];   
ReadID(device);

the expression used as argument is converted to an rvalue that has the type unsigned char * and points to the first element of the array device .

You can imagine the function and its call the following way. For clarity I changed the parameter name to distinguish the argument and the parameter

unsigned char device[2];   
ReadID(device);

//...

void ReadID( /* unsigned char device[] */ )
{
    unsigned char local_device = device;

    // this function reads 2 bytes and put them into
    // the global buffer rxBuf;
    FlashMemory_Read(ID_ADDRESS, 2);
    local_device = &rxBuf[0];
}

So what you are trying to do does not make sense.

Instead you could copy the values to the destination array the following way

void ReadID(unsigned char device[])
{
    // this function reads 2 bytes and put them into
    // the global buffer rxBuf;
    FlashMemory_Read(ID_ADDRESS, 2);
    memcpy( device, rxBuf, 2 );
}

provided that the array rxBuf contains two actual data.

I think all the people who has answered your question could not understood your small question. You are asking as array in c behave/act like a pointer why your below line of code is not working?

device = &rxBuf[0];//as you assigning the address of first character to
  //your `device array` its not going to work as device is just a character array and not array pointer

it should be like below

*device = rxBuf[0];

To copy more than one character you can use a for loop like below.

int i;
for(i=0; i<3; i++){
   *(device + i) = rxBuf[i];
 }

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