簡體   English   中英

試圖用 C 語言理解帶有指針的函數

[英]Trying to understand functions with pointers in C

#include <stdio.h>

void set_flag(int* flag_holder, int flag_position){
 *flag_holder |= (1 << flag_position);
}

void set_flag(int* flag_holder, int flag_position);

int main(int argc, char* argv[])
{
int flag_holder = 0;
int i;

set_flag(&flag_holder, 3);
set_flag(&flag_holder, 16);
set_flag(&flag_holder, 31);

我很困惑以下是做什么的? 我認為它調用的是 void set_flag() 內的指針,我不確定它是否將該值設置為 3,然后是 16,然后是 31?

set_flag(&flag_holder, 3);
set_flag(&flag_holder, 16);
set_flag(&flag_holder, 31);

讓我們擺脫按位的東西,只關注指針。

void set_flag(int* flag_holder, int flag_position) {
    *flag_holder = flag_position;
}

這個函數的目的是改變調用者的變量。 你這樣稱呼它:

int *flag;
set_flag(&flag, 5);  // flag is now 5

&一個指針, *將指針變回它所指向的位置。

flag_holder是一個指向整數的指針,它是整數在內存中的位置,一些 32 或 64 位數字。 flag_position是一個常規整數。

如果set_flag嘗試flag_holder = flag_position說“請將flag_holder指向內存位置 5”,並且很可能計算機會說“不,你不能這樣做,那不是你的記憶”並導致程序崩潰。

相反,它必須說“將您指向的數字更改為等於 5”,即*flag_holder = flag_position

&獲取它所應用的變量的地址, *獲取指針提供的地址處的值。

在函數聲明中int *將參數聲明為一個指針,一個整數的地址。 然后在函數內修改獲得的值並將其寫回給定的地址。

當您在 main 中傳遞flag_holder地址時,在set_flag(...)修改的是該地址處的值。

調用者正在傳遞一個整數的地址。 被調用者正在取消引用傳入的地址以將新值分配給該整數。 直接傳遞地址而不是值的原因是子程序可以修改整數。

新值恰好基於舊值加上翻轉單個位,具體取決於傳遞的內容。 但這實際上是與您帖子主題行不同的問題。

函數set_flag有 2 個參數:

  • int* - 指向 int 的指針
  • 整數值

然后它對數據執行一些按位或操作。

因此,在您的示例中,您將flag_holder = 0作為第一個值,將 3、16 和 31 作為第二個值。 這導致(假設32bit int):

flag_holder = 00000000 00000000 00000000 00000000    = 0 in binary
(1 << 3)    = 00000000 00000000 00000000 00001000    = 1 left shifted by 3
OR result   = 00000000 00000000 00000000 00001000    = result of | binary operation

另一個例子,如果你有 flag_holder 的另一個值:

flag_holder = 00000000 00010000 00001000 10000001
(1 << 3)    = 00000000 00000000 00000000 00001000
OR result   = 00000000 00010000 00001000 10001001

set_flag()函數使用按位運算符在位級操作 flag_holder 的值。

按位 OR | 運算符可用於設置單個位。 用於設置標志的類似技術是:

#define flag1 0x01
#define flag2 0x02
#define flag3 0x04
#define flag4 0x08
#define flag5 0x10
... you get the idea.

然后我們可以使用 OR 運算符來設置單個位:

char flags = 0;

flags |= flag1

如果您從二進制的角度考慮標志的值 - 想象一下:

flag1 = 00000001
flag2 = 00000010
flag3 = 00000100
flag4 = 00001000

你明白了! OR 運算符會將在右值中設置的任何位復制到左值,從而有效地設置位或標志。

所以做flags |= (flag1 | flag3)會導致我們的標志:

flags 00000101

我們可以使用這樣的東西來指定是否指定了特定選項。

您的示例使用了不同的技術,它始終應用 1 的位移值......想想上面的示例,其中 0x01 == 00000001

如果我們將 00000001 << 1 次移動,我們會得到 00000010。

您的 set_flag() 函數接受一個指向int的指針,這意味着它可以更改flag_holder的值,第二個參數指定向左移動 1 並隔離特定位的位置。

您應該閱讀有關按位運算符的內容,它們很有趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM