为什么这段C指针代码不能工作?

3
完全的C语言新手。我试图通过简单的代码片段来学习/理解指针。
#include <stdio.h>

void swap(int *px, int *py)
{
    int tmp;
    tmp = *px;
    *px = *py;
    *py = tmp;
}

main()
{
    int *a, *b;
    *a = 1;
    *b = 2;
    swap(&a,&b);
    printf("%d %d\n", *a, *b);
}

为什么代码无法运行?当我将主函数中的解引用运算符*去掉后,代码就可以正常运行。
从概念上讲,这似乎应该是可以运行的。我将a和b初始化为指向int 1和int 2的指针。然后,我将它们的地址发送给swap()函数,应该会交换它们所指向的值。

http://publications.gbdirect.co.uk/c_book/chapter5/pointers.html - etuardu
4
如果你编译时开启了所有警告(应该总是这样做),那么你应该已经收到了一个类型转换警告,因为&a的类型是int ** - Kerrek SB
6个回答

11

存在几个问题。首先,指针ab没有指向有效的内存。所以整数值的分配是未定义的(可能会崩溃)。其次,调用swap(假设a和b指向有效内存)不应该包括地址(目前正在发送指针变量的地址)。

进行以下更改可以使其工作:

int a, b;
a = 1;
b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);

指针a和b没有指向有效的内存。为什么它们不指向存储int 1和int 2的内存位置? - Ben G
1
整数字面量,如1和2,并不存储在内存中;它们没有地址。 - John Bode
@babonk:“*a = 1”表示取指针“a”所指向的内存位,并将值“1”放入该内存位。因此,即使上面程序中的“1”占用了一些内存,您也没有要求将该内存位置分配给“a”。常数1不占用任何内存,“&1”获取常数1的地址是无效的或未定义的。 - Shannon Severance
超级新手问题:如果整数不在内存中,那么当计算机运行程序时,它们是如何表示/使用/存储的?例如 100 + 1。这不需要将整数100和1存储在内存中吗? - Ben G
1
@babonk 大多数编译器都会将 100+1 优化为 101,但它将数字100和1存储在程序中,而不是堆栈或堆中。 如果编译器允许您通过 &100 获取程序的某些部分的地址,则程序员可能会意外执行类似于 *((&100) + 1) 的操作,这可能会覆盖正在运行的程序的一部分。 这将导致几乎不可能跟踪错误。 - jgon

6
`swap()`函数没问题,但是在主函数中你取得了指针的地址,所以你将`int**`参数传递给了`int*`参数。
int *a, *b;
swap(&a,&b);

为了解决这个问题,需要用以下代码替换 main() 中的代码 :
int a = 1, b = 2;
swap(&a,&b);
printf("%d %d\n", a, b);

请澄清,我错误地发送了一个指向指针的指针,而不是指向变量的指针? - Ben G

3
指针指向数据。指针本身不包含存储内存的空间,它只是指向现有内存的指针。因此,当您声明int *a;时,您只是拥有一个没有可用值的垃圾指针,您不能对其进行解引用。
使用指针的唯一明智方法是将它们赋予某个东西的地址(或某个分配函数的结果):
int i;
int *a = &i;  // now a points to i

因此,正确使用swap函数的方式是传递整数地址:
int i = 10;
int j = -2;

swap(&i, &j);

2

ab是未初始化的指针,对它们进行解引用会导致未定义的行为。你需要:

int main() {
    int a, b;
    a = 1;
    b = 2;
    swap(&a,&b);
    printf("%d %d\n", a, b);
    return 0;
}

0
当你说:“然后我将它们的地址发送到swap(),应该切换它们指向的内容。” 你是想要在主函数中更改指针变量内的地址值,以切换它们所指向的内存位吗?如果是这样,那么你需要再进行一步重定向:
#include <stdio.h>

void swap(int **px, int **py) {
  int *tmp;
  tmp = *px;
  *px = *py;
  *py = tmp;
}

int main (void) {
  int x, y; /* storage to point to */
  int *a, *b;

  a = &x;
  b = &y;

  *a = 1;
  *b = 2;

  printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
  swap(&a, &b);
  printf("(*a, *b, x, y) == (%d, %d, %d, %d)\n", *a, *b, x, y);
}

$ ./a.out
(*a, *b, x, y) == (1, 2, 1, 2)
(*a, *b, x, y) == (2, 1, 1, 2)

xy的值没有改变,但是a原来指向x,现在指向y,而b则相反。


0

你的方法签名有误。你要求两个指向整数的指针,但你传入了两个指向指向整数的指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接