【问题标题】:strange pointer arithmetic in for loop in CC中for循环中的奇怪指针算术
【发布时间】:2014-02-19 01:47:56
【问题描述】:

我正在使用 IAR EBW 对 msp430 进行编程。

我得到的表达式如下:

adres = (uint_fast16_t *) 0x8602 + (0x0200*i);

在 for 循环中,以便 i 随每个循环增加。出于某种原因,它会跳过两个地址中的每一个并给我:

0x8602
0x8A02
0x8E02

等等。所以 0x8802 被跳过了,0x8C02 也是如此......

为什么会这样?

//// 下面是完整代码,注意i是放在三个循环中的,每个人给出的结果都是一样的。 //// 另请注意,在调试期间检查时显示为:1,2,3...等

#include "io430.h"
#include <stdint.h>

int main( void )
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;

  // Inicjalizuj piny GPIO
  P3OUT &= ~(BIT4+BIT5);        // zeruj wartości by zapobiec krótkotrwałym impulsom
  P3DIR |= BIT4; // ustaw pin3.4 UCA0TXD oraz piny 3.0 CS, 3.1 SIMO, 3.3 CLK jako wyjście
  P3DIR &= ~(BIT5);               // ustaw pin3.5 UCA0RXD oraz 3.2SOMI jako wejście
  P3SEL |= BIT4+BIT5;         // daj funkcje TXD i RXD pinom 3.4 i 3.5, funkcje SIMO,SOMI,CLK pinom 3.1,3.2,3.3

  // Inicjalizuj ustawienia zegarów BCS
  BCSCTL1 = CALBC1_16MHZ;       // ustawia DCO na 16MHz, wyłącz XT2, LFXT1 w trybie niskiej częstotliwości
  DCOCTL = CALDCO_16MHZ;        // ustawia DCO na 16MHz
  BCSCTL2 |= BIT2;              // ustawia dzielnik SMCLK na 4

  // Ustaw flash na czyszczenie segmentów
  while(FCTL3&BIT0);            // czekaj aż będzie można inicjalizować
  FCTL2 = FWKEY + BIT6 + BIT5+BIT3+BIT2; // ustawia źródło zegara na MCLK oraz jego dzielnik dający f = 363 kHz
  FCTL1 = FWKEY + BIT1;         // czyść indywidualne segmenty
  FCTL3 = FWKEY;            // zdejmuje blokadę na pisanie i czyszczenie (tu segmentów)

  // Czyść segmenty  
  uint_fast16_t *adres;
  uint_fast8_t i=0;
  for ( i=0 ; i < 59; i++)
    {
      adres = (uint_fast16_t *) 0x8602 + i*0x0200; // ustawia wskaźnik na kolejne miejsa w pamięci. sprawdzić!!
      *adres = 0;               // wyczyść segment przez wpisanie w jego komórkę głupiego bitu
      while(FCTL3&BIT0);        // poczekaj aż generator czasowy dla flasha
    }
  FCTL1 = FWKEY;                // blokuje możliwość czyszczenia

  __delay_cycles(65000);

  // Ustaw flash na zapis danych
  while(FCTL3&BIT0);            // czekaj aż będzie można pisać
  FCTL1 = FWKEY + BIT6;         // pozwól pisać do flash

  // Pisz do flash
  uint_fast16_t szesnastka = 0;

  for ( i=0 ; i < 59; i++)
    {
      szesnastka = (0x55 << 8 ) | 0xF0;
      adres = (uint_fast16_t *) 0x8602 + (0x0200*i); // ustawia wskaźnik na kolejne miejsa w pamięci. sprawdzić!!
      *adres = szesnastka;               // wyczyść segment przez wpisanie w jego komórkę głupiego bitu
      while(FCTL3&BIT0);        // poczekaj aż generator czasowy dla flasha
    }
  FCTL1 = FWKEY;                // blokuje możliwość pisania
  FCTL3 = FWKEY + LOCK;         // ustawia blokadę na pisanie i czyszczenie


  __delay_cycles(65000);


  // Inicjalizuj ustawienia do transmisji UART
  UCA0CTL0 = 0x00;              // ustawia domyślne parametry protokołu
  UCA0CTL1 |= BIT7+BIT6;        // ustawia źródło sygnału na SMCLK
  UCA0BR0 = 0xA0;               // ustawia dzielnik 4MHz do baud rate 9600
  UCA0BR1 = 0x01;               // ustawia dzielnik 4MHz do baud rate 9600                  
  UCA0MCTL |= BIT2+BIT3;        // ustawia modulacje zegara do baud rate 9600

  UCA0CTL1 &= ~UCSWRST;         // włącza maszynę USCI

  uint8_t *ptr;

  // Wyślij wszystkie wyniki poprzez UART
  for( i=0 ; i < 59 ; i++  )
  {
  ptr = (uint8_t *) 0x8602 + i*0x0200; // ustawia wskaźnik na kolejne miejsa w pamięci. 
  while(!(IFG2&UCA0TXIFG));   // czeka na możliwość wysłania
  UCA0TXBUF = *ptr;         // wysyła dane przez UART

  ptr++;
  while(!(IFG2&UCA0TXIFG));   // czeka na możliwość wysłania
  UCA0TXBUF = *ptr;         // wysyła dane przez UART
  }


  return 0;
}

【问题讨论】:

  • 你能告诉我们实际的循环吗? i 可能在其中某处被修改...
  • 我来自哪里。你能展示整个循环吗?
  • 你知道了,谢谢你的回复!
  • 值得补充的是,uint_fast16_t 的大小不一定是 16 位。在&lt;stdint.h&gt; 中,最快 整数类型(int_fastN_tuint_fastN_t,其中N=8、16、32 或64)定义为having at least N bits
  • 是的,我同意你的看法,先生。我这样写是为了习惯。虽然我的 CPU 是 16 位,所以如果 uint_fast16_t 被认为至少有 16 位,而我的 CPU 有 16 位,这就是结果。感谢您的链接

标签: c pointers msp430 pointer-arithmetic iar


【解决方案1】:

您将第一个值转换为指向 16 位值的指针,因此添加 0x200 会将其向前移动 512 个 16 位(或 2 字节)值。

如果你这样做了:

adres = (uint_fast32_t *) 0x8602 + (0x0200 * i ) ;

会的:

0x8602
0x8E02
0x9202

要么缩小一半,要么在演员表之前做数学运算:

adres = ( uint_fast16_t *) ( 0x8602 + ( 0x0200 * i ) ) ;

【讨论】:

    【解决方案2】:

    当您进行指针添加时,您正在将指针类型的大小添加到您正在操作的指针上。例如,char* 加 1 将加 1,uint32_t* 加 1 将加 4。

    因此,我认为如果您将代码更改为:

    adres = (uint_fast16_t *) ((char*)0x8602 + (0x0200*i));
    

    【讨论】:

      【解决方案3】:

      它是指针运算,而不是整数运算。

      随着i 的增加,(uint_fast16_t *) 0x8602 + (0x0200*i) 增加0x0200*2,因为sizeof(uint_fast16_) 在这种情况下为 2。

      【讨论】:

      • 它基于sizeof(uint_fast16_t),而不是指针的大小。例如。在 32 位系统上,指针通常为 32 位长,但您可以将内存指针移动单个字节。
      • @Mario,是的,我错了。
      【解决方案4】:

      您正在将 uint_fast16* 指针增加 0x0200*i。

      当您添加到指针时,它会按基类型的大小递增,因此您会递增 2 个字节 * 0x0200*i,而不仅仅是 0x0200*i

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-07
        • 2013-06-12
        • 2016-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多