如何理解指针(*)与取地址(&)运算符?C语言函数传参疑问咨询
一、为什么analyse_inst的参数必须是char*?
你写的原代码里,mnemonic和operands都是char*类型——它们本质是指向字符串首字符的指针,存储的是字符串第一个字符在内存中的地址。
如果你的函数参数写成char mnemonic,这意味着你要把mnemonic指针指向的第一个字符(也就是字符串"add"里的'a')复制一份传给函数形参。但printf("%s", ...)要求传入的是字符串的首地址(char*类型),你传单个char进去,编译器会把这个字符的ASCII值当成内存地址来访问,这显然是非法的(会触发未定义行为,程序崩溃或者乱输出)。
而当你把参数改成char* mnemonic时,你传递的是指针本身的值(也就是字符串的首地址),函数形参拿到这个地址后,printf就能从这个地址开始,逐个打印字符直到遇到字符串结束符\0,这才是正确的用法。
二、关于传值和传引用的理解,你是对的,但要注意C语言的特殊性
你的理解基本没问题:
- 传值:把实参的副本传给形参,函数里修改形参不会影响到函数外的实参——因为两者是完全独立的变量,只是值相同。
- 传引用:把实参的地址传给形参,函数通过这个地址直接访问/修改实参所在的内存,所以修改会影响到函数外的变量。
但要注意:C语言本身并没有原生的“传引用”语法,我们平时说的C语言传引用,其实是通过传递指针的方式模拟实现的。而且哪怕传递指针,本质上还是传值——因为我们传递的是指针的副本(也就是地址值),只不过这个副本和原指针指向同一块内存,所以修改这块内存的内容会影响外部;但如果你在函数里修改指针本身(比如让形参指针指向另一个地址),外部的原指针不会变,因为形参是独立的副本。
三、修改你的代码实现“传引用”(模拟)
原代码里的mnemonic和operands指向的是常量字符串(存储在只读内存区),不能直接修改内容。所以我们可以做两个方向的修改:
1. 修改字符串的内容(需要用字符数组,而不是指向常量字符串的指针)
如果想在函数里修改字符串的内容,需要把变量改成字符数组(因为字符数组存在栈上,可修改),然后函数参数用char*(传递数组首地址,本质是传指针值,模拟传引用):
#include <stdio.h> #include <string.h> void analyse_inst(char *mnemonic, char *operands) { // 修改mnemonic的内容 strcpy(mnemonic, "sub"); // 修改operands的内容 strcpy(operands, "three from ten"); } int main() { // 用字符数组存储字符串,而不是指向常量字符串的指针 char mnemonic[10] = "add"; char operands[20] = "five to two"; analyse_inst(mnemonic, operands); // 打印修改后的结果 printf("修改后的mnemonic: %s\n", mnemonic); printf("修改后的operands: %s\n", operands); return 0; }
这里传递的是字符数组的首地址,函数里通过这个地址修改数组内容,外部的mnemonic和operands数组会跟着变化——这就是模拟的传引用。
2. 修改指针的指向(需要用指向指针的指针char**)
如果想在函数里让原指针指向新的字符串,就需要传递指针的地址(也就是char**类型),这样函数里修改的是原指针本身的内容:
#include <stdio.h> #include <string.h> void analyse_inst(char **mnemonic, char **operands) { // 让原指针指向新的常量字符串 *mnemonic = "mul"; *operands = "four times six"; } int main() { char *mnemonic = "add"; char *operands = "five to two"; analyse_inst(&mnemonic, &operands); // 打印修改后的指针指向的内容 printf("修改后的mnemonic: %s\n", mnemonic); printf("修改后的operands: %s\n", operands); return 0; }
这里我们用&mnemonic取到指针变量本身的地址,传给函数的char**形参,函数里通过*mnemonic修改原指针的指向,这样外部的mnemonic和operands指针就会指向新的字符串。
内容的提问来源于stack exchange,提问作者Tina

