【问题标题】:Getting value using indirection operator使用间接运算符获取价值
【发布时间】:2013-05-10 02:59:01
【问题描述】:

如果值存储在地址中,那么这个声明做什么

int a = 10;

它将值存储在 a 或 &a 的地址中。如果它将值存储在 a 的地址中,那么为什么我们不能像这样使用对这个变量的间接寻址:

printf("%d", *a);

如果不是,那么我们怎么能说每个值都有一个唯一的地址,我们可以使用间接运算符访问它们。

编辑:如果我认为间接仅用于指针,那么考虑一下:

int b[10];
b[0] = 4;  // Give it some value

现在我们知道 b[0] 是一个标量,可以在需要标量值的任何地方使用。但在这种情况下,我们可以像这样使用间接方式:

printf("%d", *b);  // print 4

看到我们可以在这个标量变量上使用指针,但不能在没有数组的变量声明上使用,这并不有趣。

在我看来,编译器会自动为这样的变量声明生成间接:

int a = 4;

因此,在此上不可能进行间接寻址,因为我们在其上放置了另一个不合法的间接寻址,除非在这样声明变量的情况下:

int a = 4; 
int *b = &a; 
int **c = &b;

编辑 2:您可以将 scanf("%d", &a) 作为证明,将值存储在 a 的地址中,而不是 a。

【问题讨论】:

  • 间接运算符的操作数必须是指向类型的指针。
  • 数组名的特殊之处在于它们的作用类似于指针
  • 不一定将值存储在a或&a的地址中a 可以存储在寄存器中,或者在某些情况下可以完全优化掉。 a 不是地址,它是编译器可能使用内存位置实现的int 变量。
  • @Caleb:是的,我知道a 不是地址,但我所说的问题是将值存储在地址中(即&a)。您可以将scanf("%d", &a) 作为证明。
  • 你的问题似乎是(很难说)为什么你不能说:int a = 10; printf("%d", *a);。原因是aint,而不是int *,也就是说,它是存储在地址&a的值,而不是地址本身。您说您知道a 不是地址,但如果您知道,那么应该清楚您不能使用*a 取消引用它。

标签: c arrays pointers


【解决方案1】:

在某种程度上你是对的:a 存储了一个int 并住在地址&a

但是间接只能用于指针。所以你可以做任何一个

int a = 10;
int *p = &a;
printf("%d", a);
printf("%d", *(&a));
printf("%d", *p);

【讨论】:

    【解决方案2】:

    当变量是int(而不是int *)类型时,编译器知道它需要为你做间接寻址,你不应该试图让它去做。也就是说,当您拥有int a = 10; 时,编译器将值存储在由&a(忽略寄存器)表示的内存位置,并且它知道当您编写printf("%d\n", a); 时,它需要获取存储在@ 的值987654326@ 自动执行,而无需您考虑告诉它取消引用某些内容。

    当变量的类型为int *(例如int *p)时,可以通过两种方式读取值:

    • 获取p 中保存的值(地址)
    • 获取保存在p中的地址的值

    这是两个不同的操作,所以需要两个符号:

    int  a = 10;
    int *p = &a;
    int *q = p;
    int  r = *p;
    

    当然p也有自己的地址。

    【讨论】:

    • 在什么场景下编译器会为你做间接寻址?
    • 在你写a = 10;int s = a; 的上下文中——它知道a 存储在&a 的地址中(除非该值在寄存器中,但让我们不复杂的事情)。但是没有必要告诉编译器'当我写a时,我希望你获取存储在存储a的地址中的值'。
    • 所以,我是对的,编译器会自动为所有标量值生成第一级间接,无论它是数组还是简单变量,这就是指针的工作方式。
    • 也许我的 C 术语需要重新学习,但我不认为这是间接的……虽然我同意有一个抽象的间接进行,因为变量有一个地址。 ..
    • @GradyPlayer:我同意;我不认为int s = a; 是间接的,但问题的写法似乎是 OP 试图用这样的方式思考,所以我试图用他们的方式来解决他们的问题。
    【解决方案3】:

    这里的问题不是很清楚,所以我只是解释一下情况......

    每个(全局)变量都位于内存中的某个位置。当它被赋值时,该值将在内存中的变量位置。

    如果您在 C 中使用变量,您实际上使用的是存储在变量位置的值。

    一种理解方式是,如果& 获取对象的地址,并且* 取消引用(跟随)一个指针,那么* &a 与简单的a 相同。

    【讨论】:

      【解决方案4】:

      当你这样做时

      int a = 10;
      

      编译器分配足够大的内存来容纳int。这个位置必须被识别(这是在这个特定的地方,即地址)和标记(这个位置被称为a)。然后它将数据存储在那个观点。标签使您更容易访问。如果该语言的设计方式是您只能通过指针访问位置(即取消引用它们以获取值),那将很困难。

      你可以这样说,你生活在一块土地上,可以通过精确的纬度和经度来确定。但最好为该位置保留一个名称,例如 MyHouse 等,而不是每次都参考纬度/经度。 name 和 longi/lati 指的是同一个东西。

      a 是标签。 &a 更像是longi/lati

      编辑:关于int b[10]。数组名称不是普通标签。它们还充当指针,因此您可以使用 * 取消引用它们

      【讨论】:

        【解决方案5】:

        首先,你不能在没有指针类型的任何东西上使用间接运算符。

        请记住,C 中的声明基于表达式 的类型,而不是对象;声明

        int a = 10;
        

        表示表达式 a 的类型为int,并将评估为10 的值(至少在有人为其分配不同的值之前)。所以当你写

        printf("%d\n", a);
        

        编译器知道要检索存储在绑定到表达式a 的内存位置的值。将此视为直接访问

        现在考虑声明

        int *p = &a;
        

        此声明表明 表达式 *p 的类型为 int,并将评估为 p 当前指向的任何值(在这种情况下,*p 将评估到10,因为p是用a的地址初始化的);间接操作符是声明的一部分(并且绑定到声明符*p,而不是类型说明符int)。变量p 是一个指向整数的指针,它存储了另一个整数变量的地址(在本例中为变量a 的地址)。因此,如果我们想访问整数值,我们必须取消引用 p:

        printf("%d\n", *p);
        

        这是对值10间接访问;我们不是通过变量a 访问它,而是通过p 访问它它指向 a

        【讨论】:

          猜你喜欢
          • 2018-10-28
          • 2016-06-15
          • 2010-12-13
          • 2016-01-05
          • 2015-04-23
          • 1970-01-01
          • 2015-04-09
          • 2019-04-08
          • 1970-01-01
          相关资源
          最近更新 更多