C ++ / Arduino了解uint8_t和*的用法

问题描述 投票:0回答:4

有人可以向我解释这个代码块中发生了什么吗?特别是在第3行。在ptr显着之前我有预感*。并且(uint8_t *)看起来像是一个字节...但是什么与*?它看起来像r,g和b都将评估为相同的值。

case TRUECOLOR: { // 24-bit ('truecolor') image (no palette)
  uint8_t  pixelNum, r, g, b,
          *ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS * 3];
  for(pixelNum = 0; pixelNum < NUM_LEDS; pixelNum++) {
    r = *ptr++;
    g = *ptr++;
    b = *ptr++;
    strip.setPixelColor(pixelNum, r, g, b);
  }

我主要在C#工作。

c++
4个回答
1
投票

在变量定义中使用,*表示ptr是一个指针。它存储的值是内存中另一个变量或另一个变量的一部分的地址。在这种情况下,ptr是指向imagePixels内部的一块内存的指针,并且从涉及的变量的名称开始,它是图像中的一条线。由于类型是uint8_t,这是采取任何imagePixels并使用它作为单个字节块。

在变量定义之外使用,*具有不同的含义:取消引用指针。转到存储在指针中的内存中的位置并获取值。

是的,*也可以用于乘法,提高代码阅读乐趣水平。

递增(++)指针会将地址移动到下一个地址。如果你有一个uint32_t *,地址将提前4点指向下一个uint32_t。在这种情况下,我们有uint8_t,所以地址提前一个字节。所以

r = *ptr++;

A)获得指针值。

A)推进指针后。

A)将值赋值给r。

“推进指针”阶段的确切位置是棘手的。它是在步骤A之后。在C ++ 17或更高版本中,它位于“赋值”之前,因为右边的东西和等号左边的东西之间存在分隔。但在C ++ 17之前我们可以说它是在A步之后。搜索关键词:“序列点”。

g = *ptr++;
b = *ptr++;

再做一次,获取并分配ptr的当前值,推进指针。

strip.setPixelColor(pixelNum, r, g, b);

从命名我假设这将给定像素设置为上面读取的颜色。

你不能只是

strip.setPixelColor(pixelNum, *ptr++, *ptr++, *ptr++);

因为再次排序。无法保证计算参数的顺序。这是为了允许编译器开发人员对速度和大小进行优化,如果指定了排序则不能对它们进行优化,但对于那些期望从左到右分辨率的人来说,这是一个很好的选择。我的理解是这在C ++ 17标准中仍然适用。

好。这是做什么的?

有一个很大的内存块,你想要一个只有一行。

*ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS * 3];

精确定位该行的开头并将其设置为一个哑字节数组。

for(pixelNum = 0; pixelNum < NUM_LEDS; pixelNum++) {

通用for循环。对于LED线上的所有像素。

r = *ptr++;
g = *ptr++;
b = *ptr++;

以标准8位RGB格式获取线上一个像素的颜色,并指向下一个像素

strip.setPixelColor(pixelNum, r, g, b);

将读取的颜色写入一个像素。

然后for循环将循环并开始处理下一个像素,直到该行上没有更多像素。


2
投票

第二行和第三行可以更清晰地表达:

uint8_t pixelNum;
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t *ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS * 3];

前四个变量声明应该相当简单,第五个变量声明是C#没有的。它宣称ptr是指向uint8_t的指针。该指针设置为值的地址,该值是imageLine * NUM_LEDS * 3数组中的imagePixelsth元素。因为这可能是一个不同的类型(也许是指向char的指针,谁知道),这个值被强制转换为指向uint8_t的指针。

下一个星号(*)出现在for循环体中,它用作解除引用操作符,它基本上解析了一个指针来获取实际值。

指针101

指针就像房子的街道地址。它告诉你房子在哪里,你可以找到它,但当你传递它时,你不会绕过整个房子。您可以取消引用它,这意味着您实际上可以访问该房屋。

与指针结合使用的两个运算符是星号(*)和&符号(&)。星号用于指针的声明和取消引用指针,&符号用于获取某些东西的地址。

看一下下面的例子:

int x  = 12;
int *y = &x;

std::cout << "X is " << *y; // Will print "X is 12"

我们宣布x为持有int值的12。现在我们将y声明为指向int的指针,并通过存储x的地址将其设置为指向x。通过使用*y,我们获得x的实际值,int指向的y

由于指针是一种引用类型,因此通过指针修改值会改变指向的事物的实际值。

int x = 12;
int *y = &x;

*y = 10;

std::cout << "X is " << x; // Will print "X is 10"

指针102

指针是一个很大的主题,如果有必要,我建议你花时间从不同的来源阅读它们。


0
投票

星号(*)是指针的符号。所以(uint8_t *)是指向uint8_t的指针的强制转换。然后在循环中,星号前缀为一个符号(即* ptr),该符号取消引用该指针。取消引用指针会返回指针指向的数据。

我建议阅读有关指针的内容,因为它们对于理解C / C ++至关重要。这是C++ Docs on Pointers


0
投票

MildlyInformed,我需要更多代码来运行它来解释它。我发现的一个非常有用的工具是C visualizer。它是一个在线调试工具,通过逐步逐行运行,帮助您弄清楚代码中发生了什么。它可以在:http://www.pythontutor.com/visualize.html#mode=edit找到

即使URL谈到python,它也可以做C和一堆语言。我会评论而不是发布答案,但我的代表不够高。我希望这有帮助!

(我不隶属于上述网站,除了在我感到困惑时偶尔使用它)

© www.soinside.com 2019 - 2024. All rights reserved.