【问题标题】:Resetting pointer to an array of chars重置指向字符数组的指针
【发布时间】:2016-05-28 09:55:03
【问题描述】:

我正在从 Rasp 发送 5 个字节的数据。 Pi 并使用 UART 通过 dsPIC30F 微控制器接收它们。我可以正确接收数据并将 MAXCNT 寄存器设置为所需的值。当我尝试发送第二个值时出现问题。 newResBuffer[] 中的值在第一次读取数据后不会改变。

我是指针/数组的初学者,但我怀疑我的问题可能在于我重置指针的方法。我尝试了许多不同的方法,但都没有成功。我是否正确执行了这一步?

#include <string.h>

char newResBuffer[10];
char *nR = newResBuffer;
char *nRreset = NULL;
char rxRead = 0;
int newRes = 0;
int newResFlag = 0;
int j = 0;

int main(void)
{
  nRreset = nR;    // set reset point at the beginning of newResBuffer[]

  while(1)
  {
    if(U1STAbits.URXDA)  // check if there is data available
    {
      rxRead = U1RXREG & 0xFF;  //read data from UART receive register
      *nR = rxRead;    //store data to first byte of newResBuffer[]
      nR++;            // increment pointer
      j++;

      if(j > 4)
      {
        *nR = '\0';        // null terminate the string
        newResFlag = 1;    // set the flag that new value is ready to be set
        j = 0;             // reset count variable

      }//if(j>4)

    }//if(U1STAbits.URXDA)

    if(newResFlag)         // has flag been set?
    {
      sscanf(newResBuffer, "%d", &newRes);    // convert string received to an int
      MAXCNT = (newRes * 2) - 1;   // set MAXCNT register to new value
      nR = nRreset;                // reset pointer to start of newResBuffer[]
      newResFlag = 0;              // reset flag

    }//if(newResFlag)
  }//while(1)

return 0;
}//main()

我使用诊断 LED 进行了一些测试,看起来 newResBuffer[ ] 一直被重置为我发送的第一个值。在将新的 MAXCNT 值设置为无效后,我什至尝试将数组重新初始化为全 0。

【问题讨论】:

  • 不确定sscanf(newResBuffer, "%d", &amp;newRes); 正在做你想做的事情,你有一个无限的while 循环
  • 无限循环是我的目标。至于 sscanf(),我希望获取字符串(例如 newResBuffer = {'1','2','3','4','5','\0'})并转换将其转换为 int(例如 12345)。这是错误的做法吗?
  • 显示变量声明。目前你是来自newResBuffer而不是nR-4sscanf
  • @gudok 我改为 sscanf(nR-5, "%d", &newRes)... 仍然无法正常工作。
  • 这个赋值 nR = nRreset; 使 nR 指向 NULL。这意味着在读取第二个值的第一个字节时,您正在取消引用 NULL 指针。我想你的意思是nr = newResBuffer

标签: c arrays pointers


【解决方案1】:

您重置指针的方法是正确的,尽管有一些更简单的方法可以实现它。我假设您的错误一定与设置 MAXCNT 寄存器或从接收寄存器读取新数据有关。我对 Raspberry Pi 微控制器的了解不足以帮助您,但也许您需要在将 MAXCNT 寄存器更新为新值之前对其进行刷新或刷新?

我通过用标准 C 函数替换 Raspberry Pi 特定寄存器使用来测试您的代码,以便从标准输入读取并打印到 stdout。很容易测试并看到涉及接收单个 char 数字、将其存储在字符串缓冲区中、将该缓冲区转换为 int 以及重用缓冲区的代码部分都是正确的。这是我的代码,显示正确读取了值并显示了一些附加信息以确认缓冲区地址已正确递增和重置:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

char newResBuffer[10];
char *nR = newResBuffer;
char *nRreset = NULL;
char rxRead = 0;
int newRes = 0;
int newResFlag = 0;
int j = 0;

int main(void)
{
    nRreset = nR;

    /* Printing out initial memory addresses */
    printf("newResBuffer address: %p\n", (void *) newResBuffer);
    printf("Initial nRreset address: %p\n", (void *) nRreset);
    printf("Initial nR address: %p\n\n", (void *) nR);

    while(1)
    {
        /* Using rand() % 2 to simulate data availability */
        if(rand() % 2)
        {
            /* Using getc() instead of the register to read individual digits */
            rxRead = getc(stdin);
            printf("rxRead: %c saved to nR address %p\n", rxRead, (void *) nR);
            *nR = rxRead;
            nR++;
            j++;

            if(j > 4)
            {
                *nR = '\0';
                newResFlag = 1;
                j = 0;
            }
        }

        if(newResFlag)
        {
            sscanf(newResBuffer, "%d", &newRes);
            /* Printing newRes and MAXCNT instead of setting the register */
            printf("newRes: %d\n", newRes);
            printf("MAXCNT: %d\n", (newRes * 2) - 1);
            printf("nR address before reset: %p\n", (void *) nR);
            nR = nRreset;
            printf("nR address after reset: %p\n\n", (void *) nR);
            newResFlag = 0;
        }
    }

    return 0;
}

使用输入“7594819432”测试时的输出为:

newResBuffer 地址:0x10779f060
初始nRreset地址:0x10779f060
初始nR地址:0x10779f060

rxRead: 7 保存到 nR 地址 0x10779f060
rxRead: 5 保存到 nR 地址 0x10779f061
rxRead: 9 保存到 nR 地址 0x10779f062
rxRead: 4 保存到 nR 地址 0x10779f063
rxRead: 8 保存到 nR 地址 0x10779f064
newRes:75948
MAXCNT: 151895
重置前的 nR 地址:0x10779f065
复位后的nR地址:0x10779f060

rxRead: 1 保存到 nR 地址 0x10779f060
rxRead: 9 保存到 nR 地址 0x10779f061
rxRead: 4 保存到 nR 地址 0x10779f062
rxRead: 3 保存到 nR 地址 0x10779f063
rxRead: 2 保存到 nR 地址 0x10779f064
新分辨率:19432
MAXCNT: 38863
重置前的 nR 地址:0x10779f065
复位后的nR地址:0x10779f060

我之前提到有一些更简单的方法可以让您重置指针。您实际上可以在不使用nRreset 的情况下做到这一点;因为newResBuffer 的基地址永远不会改变,你可以简单地用nR = newResBuffer 重置它。

更简单的方法是根本不使用移动指针,而只需使用代码中已有的变量j 来索引newResBuffer

您还可以使用atoi()strtol() 代替sscanf() 将字符串缓冲区转换为int(或long)。

这是实现相同目的的代码的更简单版本:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
    char newResBuffer[10];
    char rxRead = 0;
    int newRes = 0;
    int newResFlag = 0;
    int j = 0;

    while (1) {
        /* if (U1STAbits.URXDA) { */
        if (rand() % 2) {
            /* rxRead = U1RXREG & 0xFF; */
            rxRead = getc(stdin);
            newResBuffer[j++] = rxRead;

            if (j > 4) {
                newResBuffer[j] = '\0';
                newResFlag = 1;
                j = 0;
            }
        }

        if (newResFlag) {
            newRes = atoi(newResBuffer);
            /* MAXCNT = (newRes * 2) - 1; */
            printf("newRes: %d\n", newRes);
            printf("MAXCNT: %d\n", (newRes * 2) - 1);
            newResFlag = 0;
        }
    }

    return 0;
}

【讨论】:

  • 感谢您的详细回复。我完全消除了使用指针,只是用计数器变量 j 引用了数组位置。看起来我的原始代码正常工作(在我的微控制器代码中发现了另一个错误,接收缓冲区获取了 1 字节的数据过多,我从未清除过溢出错误标志),但我觉得我的更新代码现在更流畅了。谢谢!!
猜你喜欢
  • 1970-01-01
  • 2021-06-22
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
  • 2014-11-29
  • 1970-01-01
相关资源
最近更新 更多