如何修改C语言栈指针指向的内存地址?
关于修改指针自身内存地址的疑问
我刚对指针有了一点理解突破,但遇到一个看似简单的问题:如何让一个指针指向另一个指针的内存地址?示例如下:
char* foo = "foo"; // memory address: 0x7ffdabc4dbf8 char* bar = "bar"; // memory address: 0x7ffdabc4dbf0
我知道如何修改指针指向的值,比如:
foo = bar; // foo is now "bar" but the memory address is the same as before
但这样操作后,foo自身的内存地址并未改变,只是指向了bar所指向的内容。我进行了相关实验,代码如下:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void print_info(char* string1, char* string2) { printf("Memory address of string1: %p\n", &string1); printf("Memory address of string2: %p\n", &string2); printf("Value of string1: %s\n", string1); printf("Value of string2: %s\n", string2); printf("\n"); } void change(char** ptr1, char** ptr2) { *ptr1 = *ptr2; } int main() { printf("Initial values: string1 = \"foo\" string2 = \"bar\"\n\n"); char* string1 = "foo"; // Pointer to a string literal? char* string2 = "bar"; // Pointer to a string literal? print_info(string1, string2); // Modifying value, the pointer have the same memory address as before string1 = string2; printf("string1 = string2\n\n"); print_info(string1, string2); string2 = "bas"; printf("string2 = \"bas\"\n\n"); print_info(string1, string2); change(&string1, &string2); printf("change(&string1, &string2)\n\n"); print_info(string1, string2); char *ptr = string1; printf("char *ptr = string1\n\n"); printf("Memory address of ptr: %p\n", &ptr); printf("Value of ptr: %s\n\n", ptr); printf("Trying to change pointers directly:\n\n"); printf("&string1 = &string2\n"); printf("GCC: error: lvalue required as left operand of assignment\n\n"); //&string1 = &string2; printf("string1 = &string2\n"); printf("GCC: warning: assignment to ‘char *’ from incompatible pointer type ‘char **’\n\n"); string1 = &string2; print_info(string1, string2); printf("&string1 = *string2\n"); printf("GCC: error: lvalue required as left operand of assignment\n\n"); //&string1 = *string2; //print_info(string1, string2); printf("string1 = *string2\n"); printf("GCC: warning: assignment to ‘char *’ from ‘char’ makes pointer from integer without a cast\n\n"); //string1 = *string2; //print_info(string1, string2); printf("Segmentation fault (core dumped)\n\n"); printf("*string1 = &string2\n"); printf("GCC: warning: assignment to ‘char’ from ‘char **’ makes integer from pointer without a cast\n\n"); *string1 = &string2; print_info(string1, string2); printf("Corruption?\n"); return EXIT_SUCCESS; }
实验输出如下:
Initial values: string1 = "foo" string2 = "bar" Memory address of string1: 0x7fffc52760b8 Memory address of string2: 0x7fffc52760b0 Value of string1: foo Value of string2: bar string1 = string2 Memory address of string1: 0x7fffc52760b8 Memory address of string2: 0x7fffc52760b0 Value of string1: bar Value of string2: bar string2 = "bas" Memory address of string1: 0x7fffc52760b8 Memory address of string2: 0x7fffc52760b0 Value of string1: bar Value of string2: bas change(&string1, &string2) Memory address of string1: 0x7fffc52760b8 Memory address of string2: 0x7fffc52760b0 Value of string1: bas Value of string2: bas char *ptr = string1 Memory address of ptr: 0x7fffc52760d8 Value of ptr: bas Trying to change pointers directly: &string1 = &string2 GCC: error: lvalue required as left operand of assignment string1 = &string2 GCC: warning: assignment to ‘char *’ from incompatible pointer type ‘char **’ Memory address of string1: 0x7fffc52760b8 Memory address of string2: 0x7fffc52760b0 Value of string1: � @ Value of string2: bas &string1 = *string2 GCC: error: lvalue required as left operand of assignment string1 = *string2 GCC: warning: assignment to ‘char *’ from ‘char’ makes pointer from integer without a cast Segmentation fault (core dumped) *string1 = &string2 GCC: warning: assignment to ‘char’ from ‘char **’ makes integer from pointer without a cast Memory address of string1: 0x7fffc52760b8 Memory address of string2: 0x7fffc52760b0 Value of string1: � @ Value of string2: Corruption?
现提出疑问:是否可以修改栈指针指向的内存地址?还是仅通过malloc分配的堆指针才能做到?
解答
首先明确核心概念:任何变量(包括指针变量)自身的内存地址,是由编译器和运行时环境在分配时确定的,一旦分配完成就无法修改——不管这个变量存储在栈上还是堆上。
你尝试的&string1 = &string2这类操作报错,本质是因为&string1是一个右值(它仅代表变量的地址本身,不是可被赋值的存储位置),C语言不允许给右值赋值。
你之前的困惑源于混淆了两个关键概念:
- 指针变量自身的内存地址:比如
string1这个变量在栈上的存储地址(示例中的0x7fffc52760b8),这个地址是固定的,无法更改。 - 指针变量存储的指向地址:也就是指针变量的值,这个是可以修改的——比如你执行的
string1 = string2,就是把string2存储的地址赋值给string1,让string1指向string2原本指向的内容。
不管是栈上的指针(比如你定义的char* string1)还是堆上的指针(比如char** heap_ptr = malloc(sizeof(char*))),它们自身的地址都无法修改。堆上的指针只是存储位置在堆,但它自身的地址同样固定,你能修改的只是它存储的指向地址。
你实验中的错误操作(比如string1 = &string2)属于类型不匹配,&string2是char**类型,赋值给char*类型的string1会导致指针指向非法内存区域,进而出现乱码或段错误,这本身就是非法操作,和修改指针自身地址无关。
总结
- 所有变量(包括指针)自身的内存地址都无法修改,与存储位置是栈还是堆无关。
- 你能修改的是指针变量存储的指向地址(即指针的值),这在栈指针和堆指针上都能实现。
内容的提问来源于stack exchange,提问作者user1359448
相关产品推荐
相关产品推荐

