简体   繁体   English

在C语言中将字符串作为值传递:为什么此代码有效?

[英]Passing string as value in C language: why does this code work?

I had to write a function that modified a string. 我不得不写一个修改字符串的函数。 Because I need to modify the string my immediate thought was that I needed to pass the string as reference: 因为我需要修改字符串,我立即想到我需要传递字符串作为参考:

void substitution (char **str, char c1, char c2)
{
  int i;
  for (i=0; (*str[i])!='\0'; ++i)
    if (c1 == (*str[i]))
      (*str[i]) = c2;
}

However I decided to try to pass the string as value and to my surprise the program still works: 但是我决定尝试将字符串作为值传递,令我惊讶的是程序仍然有效:

void substitution(char *str, char c1, char c2)
{
  int i;
  for (i=0; (str[i])!='\0'; ++i)
    if (c1 == (str[i]))
      (str[i]) = c2;
}

I tested my program using 我测试了我的程序

int main(void)
{
   char str[]="banana"; 
   substitution(str, 'a', 'e'); 
   printf("%s\n", str); 
}

Which always returned the output "benene". 总是返回输出“benene”。 I don't understand why this is happening. 我不明白为什么会这样。 I thought that if I passed the string by value, the function would only change the string locally and that when I returned I would still obtain the original string. 我认为如果我按值传递字符串,该函数只会在本地更改字符串,当我返回时,我仍然会获得原始字符串。

Can someone help me clarify this? 有人可以帮我澄清一下吗?

The "pass by value" is only of the pointer to the string. “按值传递”仅是指向字符串的指针 Both your versions modify the individual characters of the string of the caller. 您的两个版本都会修改调用者字符串的各个字符。 The caller only passes a pointer, not the actual bytes. 调用者只传递一个指针,而不是实际的字节。

In your first version, you dereference the address of the pointer (giving you the pointer), then you dereference that pointer and work on the individual characters. 在第一个版本中,您取消引用指针的地址(给出指针),然后取消引用该指针并处理各个字符。

In your second version you dereference the pointer and work on the individual characters. 在第二个版本中,您取消引用指针并处理单个字符。


Consider: 考虑:

int main(void)
{
    char *s=0;
    example (&s);
    printf("%s\n",s);
    return 0;
}
void example(char **s)
{
    *s= malloc(6);
    strcpy(*s,"hello");
}

Function example makes variable s of main point to newly allocated memory. 函数example使main变量s指向新分配的内存。 It can do that because you passed its address, not its value (called a double pointer ). 它可以这样做,因为你传递了它的地址,而不是它的值(称为双指针 )。 But if you don't need to modify what s points to, as in your case, it is sufficient to pass a single pointer, which C does automatically when you pass an array name to a function (it takes the address of the first element and passes that). 但是,如果您不需要修改s指向的内容,就像在您的情况下一样,只需传递一个指针,当您将数组名称传递给函数时,C会自动执行(它会获取第一个元素的地址)通过那个)。

They are equivalent code. 它们是等效的代码。 In your first example you were passing a string pointer pointer, meaning you are passing the address to an address of a pointer. 在您的第一个示例中,您传递的是字符串指针指针,这意味着您将地址传递给指针的地址。 When you dereference that pointer pointer, you are left with a pointer, which is equivalent to the function you have below it. 当你取消引用那个指针指针时,你会留下一个指针,它等同于你下面的函数。

for (i=0; (*str[i])!='\\0'; ++i)

vs.

for (i=0; (str[i])!='\\0'; ++i)

The later will likely be more handy to have in your library, so you can just pass it an array value (which is a pointer), instead of an address to that value. 后者在您的库中可能会更方便,因此您可以只传递一个数组值(这是一个指针),而不是该值的地址。

C does not have the concept of "pass by reference". C没有“通过引用传递”的概念。 Pointers mimics pass by reference, but it is still ALLWAYS pass by value in C. What you are doing is passing the value of the pointer . 指针模仿传递引用,但它仍然是通过C中的传递。你正在做的是传递指针

C teachers sometimes use the term "pass by reference" in cases like this. 在这种情况下,C教师有时会使用“通过引用传递”这个术语。 I think it is a bad habit. 我认为这是一个坏习惯。 It may simplify some things, but in general, I would say that it just causes confusion in the long run. 它可能会简化一些事情,但总的来说,我会说它只会导致长期混乱。 Your question is a good example of that. 你的问题就是一个很好的例子。 It is a bit similar to when many beginners believe that arrays are pointers. 它有点类似于许多初学者认为数组是指针的时候。 They are not 他们不是

C++, on the other hand, has true pass by reference. 另一方面,C ++通过引用真正传递。 This simple program will output 42: 这个简单的程序将输出42:

void inc(int &x) { x++; }

int main() {
    int a=41;
    inc(a);
    std::cout << a << std::endl;
}

This cannot be done in C. The equivalent C program would look like this: 这不能在C中完成。等效的C程序看起来像这样:

void inc(int *x) { (*x)++; }

int main() {
    int a=41;
    inc(&a); // Take the address of a and pass it by value
    printf("%d\n", a);
}

This little thing could make it easier to understand. 这个小东西可以让它更容易理解。 C does not support overloading, but this works with a C++ compiler. C不支持重载,但这适用于C ++编译器。 Assuming you keep your second function: 假设你保留第二个功能:

void substitution(char *str, char c1, char c2)
{
  int i;
  for (i=0; (str[i])!='\0'; ++i)
    if (c1 == (str[i]))
      (str[i]) = c2;
}

you can actually rewrite your first function to: 你实际上可以将你的第一个函数重写为:

void substitution(char **str, char c1, char c2)
{
    substitution(*str, c1, c2);
}

In order to make it work in plain C, you would have to rename one of them. 为了使它在纯C中工作,您必须重命名其中一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么这段代码有效? function 的输入是“string s”,但我们给出的实际输入是“int name”。 C语言 - Why does this code work? The input for the function is "string s" but the actual input we are giving is "int name". C language 为什么奇怪的价值出现在C语言代码中不必要的%转换? - Why does the strange value come out with an unnecessary % conversion in the code in C language? 这段代码在 C 语言中究竟是如何工作的? (一个初学者问题) - How does this code exactly work in C Language? (A Beginner Question) “ C编程语言”中的代码如何工作? - how does this code from “The C Programming Language” work? 为什么编译器不适用于使用 Visual Code 的 C 语言? - Why doesn't the compiler work for C language using Visual Code? 为什么 Dennis Ritchie 的“C 编程语言”中的这个程序不起作用? - Why does this program in Dennis Ritchie's "The C Programming Language" not work? 为什么修改字符串的代码不起作用? - Why does this code to modify a string not work? 删除C字符串 - 此代码如何工作? - C string removal - how does this code work? 为什么我的C代码每次都不起作用? - Why does my C code not work everytime? 为什么此C结构代码有效? - Why does this C struct code work?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM