按值或按引用传递指针相同

Is passing pointer by value or by reference the same

在 C 中按引用传递指针和按值传递指针有什么区别?

我的理解是,当您将参数传递给方法时,会创建一个新的堆栈框架,并且除非通过引用传递,否则这些值将被复制到不同的内存地址。如果通过引用传递内存地址。

在使用指针时,我注意到如果我按值传递 char* 并在我 return 返回主堆栈帧时在不同的堆栈帧中修改它,则 ptr 的值已被修改。

我写了简短的代码来展示我在说什么。

//test pointer ref
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void passbyval(char const *lit,char* str){
    printf("---passbyval---\n");
    printf("%s\t%p\n",lit,&lit);
    //modify string
    strncat(&str[2],"/",1);
    printf("%s\t%p\n",str, &str);
}
void passbyref(char const **lit, char** str){
    printf("---passbyref---\n");
    printf("%s\t%p\n",*lit,&*lit);
    //modify string 
    strncat(&(*str)[1],"/",1);
    printf("%s\t%p\n",*str,&*str);
}
int main(){

    char const *litstr = "hello this is a test";
    char *str = (char*)malloc(sizeof(char)*100);
    scanf("%[^\n]",str);
    printf("---main---\n");
    //print original value and address
    printf("%s\t%p\n",litstr,&litstr);
    printf("%s\t%p\n",str,&str);
    passbyval(litstr,str);
    //modified value and address from pass by value 
    printf("\nretfromval:%s\t%p\n",str,&str);
    passbyref(&litstr,&str);
    //modified value and address from pass by ref
    printf("\nretfromref:%s\t%p\n",str,&str);
    free(str);
    return EXIT_SUCCESS;
}

输出

不通过引用传递是一种好习惯吗char*您想在 void 方法中修改?

如果指针引用的值是通过引用隐式传递的,为什么我会对指针使用引用传递感到困惑。

也许我遗漏了什么,有人能更好地解释一下吗?

When working with pointers I noticed that if I pass a char* by value and modify it in a different stack frame when I return back to the main stack frame the value of the ptr has been modified.

None 您的示例执行此操作。此外,您的代码的 none 会打印 litstrstr 的值。要打印指针的值,请删除所有 printf 调用中的 &。然后你会看到指针的值在调用例程和被调用例程中是相同的。

main 中,printf("%s\t%p\n",litstr,&litstr); 打印:

  • 内存中起始地址为 litstr 的字符串(因为 %slitstr)和
  • litstr 的地址(不是值)(因为 %p&litstr)。

类似地,printf("%s\t%p\n",str,&str); 打印 str 处的字符串和 str 的地址。

passbyval中,printf("%s\t%p\n",lit,&lit);打印lit处的字符串和lit的地址。由于litpassbyval的参数,它有自己的地址,不同于litstr的地址。如果您打印了 litstrlit 的值而不是它们的地址,您会看到它们是相同的。

类似地,printf("%s\t%p\n",str, &str); 打印 str 处的字符串和 str 的地址。 passbyval中的参数str的地址与main中的局部对象str的地址不同,但它们的值相同。

passbyref中,printf("%s\t%p\n",*lit,&*lit);打印lit处的字符串和*lit的地址。由于litmainlitstr的地址,*litlitstr的地址,所以&*lit是[=10=的地址]. litstr 的值将是 *lit.

类似地,printf("%s\t%p\n",*str,&*str);打印*str处的字符串和*str的地址,即mainstr的地址。

您需要了解指针和数组的工作原理。

pointer 是一个独立的对象,有自己的引用,持有底层对象的引用。

char *p = "aaa";

print("%p\n", (void *)p); //prints the reference of the string literal "aaa"
print("%p\n", (void *)&p); //prints the reference of the pointer `p`

数组是连续的内存块。数组衰减 为指针。这些指针在内存中没有物理表示,只是对数组第一个元素的引用。

char p[] = "aaa";

print("%p\n", (void *)p);  //reference of the first element 
                           //of the array p the type is `char *` 
                           //(pointer to char)
print("%p\n", (void *)&p); //reference of the first element of the 
                           //array p the type is `char (*)[4]` 
                           //(pointer to an array of 4 char elements)

What is the difference between passing a pointer by reference and passing a pointer by value in C?

在C语言中没有通过引用传递指针,所有变量都是按值传递,甚至是指针。

My understanding is when you pass arguments to methods a new stack frame is created and those values are copied to different memory addresses unless passed by reference. If passed by reference the memory addresses are passed.

同样,指针不是通过引用传递的,传递的是指针中存储的值的副本,它指向的地址,你可以通过更改函数内部指针的值,并检查它如何反映在原始指针上,扰流板,它没有。

When working with pointers I noticed that if I pass a char by value and modify it in a different stack frame when I return back to the main stack frame the value of the ptr has been modified.*

你传递的是一个地址,一个存储一些数据的内存位置,当你更改存储在该内存地址中的数据时,无论你在哪里做,它都是永久性的,事实上这是其中之一使用指针的优点,您可以在声明范围之外更改某些变量的内容。

What is the difference between passing a pointer by reference and passing a pointer by value in C.

在 C 中,有多种方法可以在将参数传递给函数之前对其进行预处理。

  • 不处理
    将参数的副本提供给函数。 char *s = ...; puts(s);puts() 得到一份 s.

  • 普通参数提升
    在将副本提供给函数之前,参数被提升为 int, unsigned, double, ...float fl = 12.5f; printf("%g", fl); printf() 得到一份 double 12.5.

  • 函数转换为地址
    tss_create(tss_t *key, tss_dtor_t dtor);一样,tss_dtor_t是函数指针类型void (*)(void*)tss_create(... , foo) 不采用函数 foo() 并传递它。而是传递函数地址的副本。

  • 数组转换为其第一个元素的地址
    使用 char s[] = "Hello; puts(s);&s[0] 的副本被传递给 puts()

现在,这些是不是像 OP 的

是的。

char *end[1]; strtod("123.4", end);从调用者的角度来看end在里面调整了整个 strtod() 等从调用者的 POV 中表现和闻起来像“通过引用传递”。这在技术上仍然是“传递副本”,但副本是参数第一个元素的地址。

除此之外,我看不到“在 C 中通过引用传递指针和通过值传递指针”之间的差异。