当应用程序运行时,如何跟踪指针的位置?
指针存储为任何其他变量;它们通常采用与 a 相同的大小unsigned long
,但这绝不是保证,只是为了让您了解它们是如何实现的。编译器可以自由地进行各种各样的优化,因此指针可能存储在内存中,它们可能存储在寄存器中,或者如果它们被优化掉,它们可能仅作为假设实体存在。
考虑以下代码:
void foo(void) {
char *c;
char buf[100];
for (c=buf; c < buf+100; c++ {
c = '0';
}
}
在这种情况下,该变量c
用于将 ASCII 字符写入数组0
中的每个字符。可能只存在于寄存器中,因为它不会超出此功能。(有更好的方法来编写此代码。)buf
c
考虑以下代码:
struct foo {
char name[10];
struct foo *next;
}
在这种情况下,成员next
是指向更多struct foo
对象的指针——例如,这些事物的链表。这些指针必须存储在内存中,因为它们是这些对象契约的一部分——它们必须在那里。也没有办法绕过这些指针——它们指向的对象可以根据程序员的心血来潮替换为其他对象。而且,由于这些对象的数量完全在运行时确定,因此编译器不能只跟踪其符号表中的地址,就像对堆栈分配的变量一样。
那么我将如何直接更改存储在指针所持有的地址处的对象呢?
"foo"
您的示例在代码中使用字符串使这变得复杂。它们保存在进程地址空间的只读内存中,因此您无法修改它们。(惊喜!)如果你用另一种方法初始化字符串,你可以通过指针修改数据:
char *c = malloc(10);
strcpy(c, "hello");
c[0] = 'H';
printf("c: %s\n", c);
这将覆盖通过指针可用的分配空间中的h
with 。像访问数组一样访问指针与像这样重写指针访问相同:H
c
c[0] = 'f';
c+0 = 'f';
而且,实际上,数组访问非常相似——数组的名称与指向其第一个元素的指针相同。
这有点复杂;Expert C Programming一书以惊人的细节涵盖了指针,非常物有所值。