我在理解以下使用指针的代码时遇到了一些问题。该代码是为AVR uC ATMega328pb
制作的。编写代码是为了每100ms读取0-255的正弦值,并将这些值写入比较标志。然后当Counter到达比较标志时,它启用ISR(中断服务程序),它根据0-255,255的最高亮度的比较标志使LCD变暗。
首先是正弦定义: PS。:代码工作正常
char SIN_SAMPLE_LENGTH 40;
uint8_t sinOut[] = {0, 1, 6, 13, 24, 37, 52, 69, 88, 107, 127, 147, 166, 185, 202, 217, 230, 241, 248, 253, 255, 253, 248, 241, 230, 217, 202, 185, 166, 147, 127, 107, 88, 69, 52, 37, 24, 13, 6, 1};
uint8_t *sinSample = sinOut;
我知道指针*sinSample
存储了sinOut
的内存地址,但不应该存在&sinOut
?
然后我有一个主循环
int main(void)
{
int cnt = 0; //count
sei();
Init_IO();
Init_T0();
while(1)
{
if(HasOneMillisecondPassed()){ //function returns true when one millisecond passes
cnt++; //counting up on 1ms count
if(cnt >= 100){ // when it reaches 100ms do this
cnt = 0; //restore count on 0
if(sinSample >= sinOut + SIN_SAMPLE_LENGTH){
sinSample = sinOut;
}else{
sinSample++;
}
OCR0A = *sinSample;
}
}
}
}
void Init_T0()
{
OCR0A = *sinOut;
TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0A1) | (1 << COM0A0);
TCCR0B= (1 << CS00) | (1 << CS01);
TIMSK0 = (1 << OCIE0A);
}
我不理解
中的部分 if(sinSample >= sinOut + SIN_SAMPLE_LENGTH)
直到
OCR0A = *sinSample
更具体地说,sinOut + SIN_SAMPLE_LENGTH
如何影响if语句以及sinSample = sinOut;
的含义
谢谢!
答案 0 :(得分:2)
sinSample
是指向sinOut
数组中当前元素的指针。当你这样做时,它开始指向数组的第一个元素:
uint8_t *sinSample = sinOut;
每次程序都这样做:
sinSample++;
它指向数组的下一个元素。
sinOut + SIN_SAMPLE_LENGTH
是指向sinOut
数组末尾的指针,因为SIN_SAMPLE_LENGTH
是数组中元素的数量。因此,
if (sinSample >= sinOut + SIN_SAMPLE_LENGTH)
测试我们是否将指针递增到数组的末尾。发生这种情况时,代码会将其设置回数组的开头。结果是它在数组中循环。
这完全等同于使用索引变量循环遍历数组,例如
int sinIndex = 0;
while(1)
{
if(HasOneMillisecondPassed()){ //function returns true when one millisecond passes
cnt++; //counting up on 1ms count
if(cnt >= 100){ // when it reaches 100ms do this
cnt = 0; //restore count on 0
if(sinIndex >= SIN_SAMPLE_LENGTH){
sinIndex = 0;
}else{
sinIndex++;
}
OCR0A = sinOut[sinIndex];
}
}
}
在C中,这两个表达式总是等价的:
array[index]
和
*(array + index)
因为当一个数组在大多数表达式中用作R值时,它会衰减到指向其第一个元素的指针,并且指针算术会按指针所指向的对象的大小计算。
这是理解C指针和数组的基础,所以如果它仍然没有沉入,请返回并重读教科书中的那一章。
答案 1 :(得分:0)
uint8_t *sinSample = sinOut;
是正确的。或者,uint8_t *sinSample = &sinOut[0];
当指针sinSample
到达sinOut
缓冲区的末尾时,它被“包裹”回到开头以发出连续信号。
答案 2 :(得分:0)
这基本上是一个可互换使用的数组和指针语义的例子sinOut + SIN_SAMPLE_LENGTH
与sinOut[SIN_SAMPLE_LENGTH]
相同。
或者,您可以将指针推进sinSample++
视为sinSample[index++]
答案 3 :(得分:0)
关于你的问题:
*我知道指针 sinSample存储sinOut的内存地址,但不应该存在&amp; sinOut?
在C中,指的是数组名称降级为数组第一个字节的地址。所以这一行:
uint8_t *sinSample = sinOut;
将sinOut
数组的地址分配给sinSample
,因此不需要address of
运算符&
。因此,不应使用address of
运算符。