试图用C中的指针来理解函数

时间:2016-09-17 19:43:02

标签: 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);

5 个答案:

答案 0 :(得分:1)

让我们摆脱按位的东西,只关注指针。

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表示说&#34;请将flag_holder指向内存位置5&#34;并且很可能计算机会说'不,你不能这样做,那不是你的记忆&#34;并使程序崩溃。

相反,它必须说&#34;将您指向的数字改为等于5&#34;这是*flag_holder = flag_position

答案 1 :(得分:0)

&获取应用它的变量的地址,*获取指针提供的地址的值。

在函数声明中int *声明参数为指针,即整数的地址。然后在函数内获取修改后的值并将其写回给定的地址。

当您在main中传递flag_holder的地址时,此地址的值将在set_flag(...)内修改。

答案 2 :(得分:0)

调用者正在传递整数的地址。被调用者解除引用传入的地址以为该整数分配新值。传递地址而不是直接传递值的原因是子例程可以修改整数。

新值恰好基于旧值加上翻转各个位,具体取决于传递的内容。但这实际上是与帖子主题相关的一个单独问题。

答案 3 :(得分:0)

函数set_flag有两个参数:

  • int* - 指向int
  • 的指针
  • 整数值

然后它对数据执行一些按位OR运算。

因此,在您的示例中,您将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

答案 4 :(得分:0)

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运算符会将rvalue中设置的任何位复制到左值,有效地设置位或标志。

这样做flags |= (flag1 | flag3)会导致我们的标志:

flags 00000101

我们可以使用类似的东西来指定是否指定了特定选项。

您的示例使用不同的技术,它始终应用位移值1 ...想象一下,如上例中的0x01 == 00000001

如果我们转移00000001&lt;&lt;我们有一次获得00000010。

你的set_flag()函数正在接受指向int的指针,这意味着它可以更改flag_holder的值,第二个参数指定向左移动1的位置并隔离特定的位。

你应该阅读有关按位运算符的信息。