[英]C++ / Arduino understanding the usage of uint8_t and *
有人可以向我解釋此代碼塊中發生了什么嗎? 特別是在第3行上。在ptr顯着之前,我有一個*的預感。 而且(uint8_t *)
看起來像是(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#工作。
第二和第三行可以更清晰地表達:
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
。 該指針設置為值的地址,該值是imagePixels
數組中的imageLine * NUM_LEDS * 3
第imageLine * NUM_LEDS * 3
個元素。 由於這可能是另一種類型(可能是指向char
的指針,誰知道),因此將該值uint8_t
轉換為指向uint8_t
。
星號( *
)的下一次出現在for循環主體中,在該處用作取消引用運算符 ,該運算符基本上會解析指針以獲取實際值。
指針就像房子的街道地址。 它向您顯示房子的位置,以便您可以找到它,但是當您繞過它時,就不會繞過整個房子。 您可以取消引用它,這意味着您可以實際訪問房屋。
與指針結合使用的兩個運算符是星號( *
)和與號( &
)。 星號用於指針的聲明並取消引用指針,“與”號用於獲取某對象的地址。
看下面的例子:
int x = 12;
int *y = &x;
std::cout << "X is " << *y; // Will print "X is 12"
我們將x
聲明為一個擁有值12
的int
。 現在,我們將y
聲明為一個指向 int
的指針 ,並通過存儲x
的地址將其設置為指向x
。 通過使用*y
,我們可以訪問x
的實際值,即y
指向的int
。
由於指針是引用的一種,因此通過指針修改值會更改所指事物的實際值。
int x = 12;
int *y = &x;
*y = 10;
std::cout << "X is " << x; // Will print "X is 10"
指針是一個很大的主題,建議您花些時間從不同的來源閱讀有關指針的信息。
在變量定義中使用*
表示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
循環將循環並開始處理下一個像素,直到該行上沒有更多像素為止。
消息靈通,我將需要更多代碼來運行它來解釋它。 我發現一個非常有用的工具是C可視化工具。 這是一個在線調試工具,可幫助您逐步一步一步地了解代碼中正在發生的事情。 可以在以下位置找到它: http : //www.pythontutor.com/visualize.html#mode=edit
即使該URL談論的是python,它也可以使用C語言和多種語言。 我本來可以發表評論而不是發布答案,但我的代表不夠高。 我希望這有幫助!
(我不隸屬於上述網站,只是在困惑時偶爾使用它)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.