-1

我在 youtube 上观看 Richard Buckland 讲座,他展示了指针的工作原理,但我在这里遇到了一些问题,据他说我们使用指针,因为有时我们可能不知道包含值的变量例如

void main()
{
    int x=20,y=30;
    task(x,y)
    getch();
}
void task(int x,int y)
{}

因此它将创建两个变量 x 和 y 的 in task() 副本,它们完全独立于原始变量,因为 task() 不知道原始变量,因此我们使用指针,以便 task() 可以直接访问main() 变量 x 和 y 的地址。

因此,如果我们说 &x 它指的是 x 的值所在的地址,但如果我们说 *x 这意味着 *20 这类似于地址 20 上的值,对吗?如果我们遵循 C 中指针的概念,它是正确的。

但不是返回位于地址 20 上的值,而是显示“无效间接”错误。

不是我不知道那个错误,而是c编译器给我这个错误的原因。我仍然遵循指针的概念,但方式不同。所以我想在概念上我是正确的,但在语法上我还是错了。为什么?

4

4 回答 4

2

*20 这类似于地址 20 上的值,对吗?

对,或多或少,但是

  • 它实际上是从address开始20的值。为了让编译器知道值的大小和表达式的类型,它必须知道你的意思是什么类型的值,所以你必须转换 20适当的指针类型。例如,(int*)20是一个指向-的指针int*((int*)20)类型也是int
  • 您不能安全地像这样“编造”一个地址,因为您实际上不太可能被分配了一个包含 address 的内存块20
于 2012-09-21T17:23:50.830 回答
1

我不太明白你的意思(你的英语太差了!),但如果我理解正确,你想取消引用一个指定为整数的常量地址,如下所示:

int someVar = *20;

现在的类型20是int,不是指针类型,所以不能解引用。您必须将其转换为适当类型的指针:

int someVar = *(int *)20;

是的,这很可能会出现段错误。

于 2012-09-21T17:22:21.267 回答
1

您必须了解的是,C 没有像 C++ 那样的“通过引用”的概念。这意味着无论变量的类型如何,编译器都会创建您传递的任何变量的副本。副本的保存位置取决于编译器、体系结构、优化级别等。通常您不必担心也不知道它保存在哪里。真正重要的是在一个函数中你得到一个副本。

理论上,您可以通过执行以下操作来访问内存的任何地址:

int *var = ((int*) 0xdeadbeef);
*var = 3;

含义:将值0xdeadbeef转换为整数指针并将其保存在var. 然后将值 3 保存在从0xdeadbeef. 虽然这是正确的 C,但您肯定会遇到段错误,因为今天的操作系统使用内存控制器让您可以访问一组有限的地址/块。

当你这样做时:

int var = 10;

编译器会将值 10 存储在某处(它可能存储在寄存器中,但我们假设编译器将其存储在 RAM 中)。作为 C 程序员,您通常不会关心它在哪里,链接器会处理正确的地址。

我们来看看这段代码

void foo(int f)
{
   /* do something with f */
}

void bar(int g)
{
    int f1 = 2;
    f1 += g;
    foo(f);
}

编译器如何将其翻译成汇编程序?它可能看起来像这样

foo:
0xa0000000: load in register 1 the 4-byte value @ 0x12abcd00
0xa0000004: /* do something with register 1 */
0xa0000008: /* do something else with register 1 */
...
bar:
0xa0000c00: load in register 3 the 4-byte value @ 0x12ad0004
0xa0000c04: load in register 4 the value 2
0xa0000c08: add register 3, register 4 (result saved in 'result register')
0xa0000c0b: save the content of 'result register' @ 0x12abcd00 (look at the first line)
0xa0000c10: jump 0xa0000000  (call foo)

这同样适用于指针。指针或多或少是一个整数变量。它们由指针存储的值是地址。与整数的区别在于您可以访问(=取消引用)存储在该地址的值。您可以通过使用*运算符来执行此操作(参见第一个示例*var = 3)。运算符返回变量的&地址。

所以当你有

void foo(int *x)
{
    *x = 3;
}

void bar(void)
{
    int i = 9;
    int *i_ptr = &i;
    foo(i_ptr);
    /* i is 3 */
}

C 创建 的副本i_ptr,但副本的存储值如果i_ptr仍然与 的地址相同i,因此foo可以取消引用它并修改 的值,i即使i未在 中定义foo

那么,我们什么时候在 C 中使用指针呢?通常,这些是使用指针时最常见的情况:

  • 我们想修改一个我们没有在函数中声明的变量
    • 例如,我们需要一次返回超过 1 个值
  • 我们使用动态分配的内存(参见malloc, realloc, calloc
  • 我们使用字符串
于 2012-09-21T23:34:14.597 回答
0

我想你想说的是:

void task(int *px, int *py)
{
    /* get the addresses of two integers */

    *px += 10; /* change the value of the integer px is pointing to */
    *py += 20; /* change the value of the integer py is pointing to */
}

void main()
{
    /* make a space on the stack for two integers, assign values */
    int x=20;
    int y=30; 

    /* display those values */
    printf("x=%d, y=%d", x, y);

    /* pass the address of each value to a function */
    task(&x,&y);

    /* display the changed values*/
    printf("x=%d, y=%d", x, y);

    getch();
}

因为这会传递x 和 y的地址,所以函数 task() 可以更改它们的值。

于 2012-09-21T17:23:59.037 回答