将指针传递给函数不会更改其值

时间:2017-11-10 14:50:00

标签: c

我面临一种奇怪的行为。我的C知识还不足以理解正在发生的事情。

我在Code Composer Studio中使用TI的C编译器(用于CC3220SF)。 我通常会写这个函数:

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];
}

(注意:这里我没有传递长度,因为它被设计固定为2)。

我在这里使用它:

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

从许多答案中指出,编译器以同样的方式处理声明为*或[]的参数,其值是第一个元素的地址(指针)。

两种意外行为:

  1. 编译器警告我,在ReadID函数中声明了'device'变量但从未引用
  2. 调试代码,我注意到在ReadID函数中,设备字节指向rxBuf值,但在调用ReadID()的函数中,它们总是读为0。
  3. 这里有什么问题,为什么?

    预期的行为是设备变量应该指向rxBuf,即使ReadID结束,因为指针已设置为rxBuf的地址。 相反,地址似乎只在本地更改!

4 个答案:

答案 0 :(得分:3)

您的问题类似于此常见问题解答:Dynamic memory access only works inside function

由于数组device[]在作为参数传递时会衰减为unsigned char* device,因此您最终会得到一个指针device ,它是该函数的本地。将本地副本分配到某个位置意味着它只会持续到函数内部。

但是因为你在调用者中拥有的是一个数组,而不是一个指针,这表明你完全误解了数组和指针是如何工作的。最好的建议是重新阅读C编程书中的那些章节。

你实际上打算做的事情可能就是这样:

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

作为旁注,具有512字节的全局变量,各种函数写入,是可怕的程序设计。正确的设计就是要有一个功能,而不是:

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

答案 1 :(得分:1)

您只是更改设备指向本地的位置。

你想做的事情就是这样:

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);
}

另请注意,rxBuf&rxBuf[0]指向内存中完全相同的地址。

答案 2 :(得分:1)

  

编译器警告我在ReadID函数中'device'   变量已声明但从未引用

函数中没有使用参数device的值,因此该参数没有意义。

考虑到函数参数是其局部变量。

  调试代码,我注意到了ReadID函数里面的内容   device bytes指向rxBuf值,但是在调用的函数中   ReadID()他们总是读0。

您要做的是更改数组,但数组不是可修改的左值。当声明数组类型的变量时,它不能更改其类型并表示不同的数组。

在此次电话会议中

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

用作参数的表达式将转换为类型为unsigned char *的rvalue,并指向数组device的第一个元素。

您可以通过以下方式想象功能及其调用。为清楚起见,我更改了参数名称以区分参数和参数

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];
}

所以你要做的事情没有意义。

相反,您可以通过以下方式将值复制到目标数组

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 );
}

如果数组rxBuf包含两个实际数据。

答案 3 :(得分:1)

我认为所有回答你问题的人都无法理解你的小问题。您问array c中的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 表现/表示为什么下面的代码行不起作用?

*device = rxBuf[0];

应该如下所示

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

要复制多个字符,您可以使用如下所示的for循环。

function oSelect(id, status, e) {
  selID = id;
  rejflag = $("#kcdimensionlist").getRowData(id)['rejectedi'];
  $("#kcdimensionlistV7").setColProp('rejectedi', {
    editoptions: {
      dataUrl: '/QMSWebApp/GenericControllerServlet?lifecycle=twowayoptionlist'
    },
    defaultValue: 0
  });
  $("#kcdimensionlistV7").setColProp('rechecki', {
    editoptions: {
      dataUrl: '/QMSWebApp/GenericControllerServlet?lifecycle=threewayoptionlist_NA'
    },
    defaultValue: 0
  });

  var target = $(e.target);

  if (!target.is("img")) {

    if (id && id !== lastsel) {
      $("#kcdimensionlistV7").jqGrid('restoreRow', lastsel);

      //This line works fine but when commented out and modified to next line it fails
      //$("#kcdimensionlistV7").jqGrid('editRow',id,true);
      $("#kcdimensionlistV7").jqGrid('editRow', id, true, errorfunc: eFunc);
      lastsel = id;
    }

  }
};