首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ / Arduino理解uint8_t和*的用法

C++ / Arduino理解uint8_t和*的用法
EN

Stack Overflow用户
提问于 2017-12-18 02:39:33
回答 4查看 875关注 0票数 0

有人能向我解释一下这个代码块是怎么回事吗?特别是在第3行。我有一个预感*在ptr是重要的。(uint8_t *)看起来就像一个字节.但这是怎么回事?它看起来也像r,g,和b都将计算到相同的值。

代码语言:javascript
复制
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#工作。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-12-18 03:12:24

在变量定义中使用的*表示ptr是一个指针。它存储的值是另一个变量或另一个变量的一部分的内存地址。在本例中,ptr是指向imagePixels内部内存块的指针,从所涉及变量的名称来看,它是图像中的一行。因为类型是uint8_t,所以这将获取任何imagePixels,并将其作为单个字节块使用。

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

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

递增(++)指针将地址移动到下一个地址。如果您有一个uint32_t *,则地址将前进4,指向下一个uint32_t。在本例中,我们有uint8_t,所以地址是一个字节。所以

代码语言:javascript
复制
r = *ptr++;

( A)在指针处获取值。

在A之后)前进指针。

在A之后将价值分配给r。

准确地说,“前进的指针”阶段的走向是棘手的。这是在步骤A之后,在C++17或更高的地方,在“赋值”之前,因为现在在等号的右边和左边的东西是分开的。但是在C++17之前,我们所能说的只是在步骤A之后,搜索关键词:“序列点”。

代码语言:javascript
复制
g = *ptr++;
b = *ptr++;

再次执行,在ptr获取和赋值当前值,提前指针。

代码语言:javascript
复制
strip.setPixelColor(pixelNum, r, g, b);

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

你不能就这样

代码语言:javascript
复制
strip.setPixelColor(pixelNum, *ptr++, *ptr++, *ptr++);

又是因为测序。不能保证参数的计算顺序。这是为了允许编译器开发人员在指定顺序的情况下对速度和大小进行优化,但对于那些期望从左到右解析的人来说,这是一个极大的打击。我的理解是,这在C++17标准中仍然是正确的。

好的。那这是在做什么?

有一个很大的内存块,您希望从其中只有一行。

代码语言:javascript
复制
*ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS * 3];

找出该行的开头,并将其设置为被视为一个哑字节数组。

代码语言:javascript
复制
for(pixelNum = 0; pixelNum < NUM_LEDS; pixelNum++) {

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

代码语言:javascript
复制
r = *ptr++;
g = *ptr++;
b = *ptr++;

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

代码语言:javascript
复制
strip.setPixelColor(pixelNum, r, g, b);

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

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

票数 1
EN

Stack Overflow用户

发布于 2017-12-18 02:56:22

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

代码语言:javascript
复制
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数组中的第四个元素。由于这可能是另一种类型(可能是指向char的指针,谁知道),因此该值被转换为指向uint8_t的指针。

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

指针101

指针就像房子的街道地址。它告诉你房子在哪里,这样你就能找到它,但是当你经过它的时候,你就不会在整个房子周围走动。你可以取消它,这意味着你实际上可以参观房子。

与指针一起使用的两个运算符是星号(*)和符号(&)。星号用于指针的声明和取消指针的引用,符号用于获取某物的地址。

请看下面的示例:

代码语言:javascript
复制
int x  = 12;
int *y = &x;

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

我们将x声明为保存值12int。现在我们将y声明为指向int的指针,并通过存储x的地址将其设置为指向x,通过使用*y访问x的实际值,即y所指向的int

由于指针是一种引用类型,通过指针修改值将更改所指向的事物的实际值。

代码语言:javascript
复制
int x = 12;
int *y = &x;

*y = 10;

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

指针102

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

票数 2
EN

Stack Overflow用户

发布于 2017-12-18 02:51:03

星号(*)是指针的符号。因此,(uint8_t *)是指向指向uint8_t的指针的转换,然后在循环中,星号以取消引用该指针的符号(即*ptr)为前缀。删除指针将返回指针所指向的数据。

我建议阅读一些关于指针的文章,因为它们对于理解C/C++至关重要。这是指针上的C++文档

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47861474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档