2

I'm reading a book the c programming language authored by Brian W. Kernighan and Dennis M. Ritchie.

The book lists code below

void strcpy(char *s, char *t){
    while((*s = *t) != '\0'){
        s++;
        t++;
    }
}

and says:

Because arguments are passed by value, strcpy can use the parameters s and t in any way it pleases

which I'm not agreed with. Why above arguments are passed by value?

According to another book C how to program:

In C, you use pointers and the indirection operator to simulate call-by reference. When calling a function with arguments that should be modified, the addresses of the arguments are passed.

In latter point of view, it's definitely call-by-reference.

Please tell me which way is correct and why, thanks!

btw, after assignment *s = *t, which one is compared with '\0'? *s or *t?

Andy Lin
  • 397
  • 1
  • 2
  • 21
  • 1
    There is no concept in C to pass by reference like C++ has. – Ilan Keshet Jun 27 '18 at 03:21
  • In C++ you can pass by reference -- which indirectly is passing a pointer to the field you are passing – Ilan Keshet Jun 27 '18 at 03:22
  • All parameters are locals to the function, C only give parameter by copy, aka value. Here `strcpy` take two pointer value – Stargateur Jun 27 '18 at 03:22
  • Both are correct. You are simulating passing by reference. – Ilan Keshet Jun 27 '18 at 03:25
  • oh....I think that's why author says: "simulate" call-by-reference. The way C adopts is: 1. pass address by value to function 2. change value by using * operator – Andy Lin Jun 27 '18 at 03:25
  • right. It isn't actually passing by reference – Ilan Keshet Jun 27 '18 at 03:26
  • It is passing by value, and the value you are passing is the address of an object. The callee can use that address to reference the object. – William Pursell Jun 27 '18 at 03:28
  • "In latter point of view, it's definitely call-by-reference." No. That is passing the pointer by value. When an array is passed, the true argument passed is the array converted to the address of the first element. This is like "pass by reference". Yet the parameter received, is a pointer, or pass by value. – chux - Reinstate Monica Jun 27 '18 at 03:50
  • "btw, after assignment *s = *t is held, which one is compared with '\0'? *s or *t?" Neither. The result of the expression (*s = *t) is compared with '\0'. In C, the result of an '=' expression is the value being assigned. – OregonJim Jun 27 '18 at 04:19
  • @IlanKeshet, yes, there *is* the concept of pass-by-reference in C, and this question is an example of it. The term "pass-by-reference" was redefined by newer languages, but it existed and was called exactly that in C, long before C++ was invented. See this discussion: https://stackoverflow.com/questions/33622787/are-pointers-considered-a-method-of-calling-by-reference-in-c?rq=1 – OregonJim Jun 27 '18 at 04:31
  • You are completely incorrectly. C has no concept of pass-by-reference. @OregonJim. Even in that link you provided me the person who has the correct answer even states there is no concept of it – Ilan Keshet Jun 27 '18 at 07:05
  • @OregonJim this is literally copy + paste from the marked answer: "you cannot pass by reference in C but can use pointers as an alternative" – Ilan Keshet Jun 27 '18 at 07:06
  • @IlanKeshet, I beg to differ. We called it pass by reference in the 1970s. The problem is, there are now multiple definitions of the term pass-by-reference. It's merely a question of defining the term. In C, when you pass a pointer to a function, you are passing by reference (a pointer is a REFERENCE to an object). Whether that reference is a copy or an alias is a matter of semantics - the result is identical. – OregonJim Jun 27 '18 at 18:44
  • @OregonJim I do agree, you "simulating" passing the "object" by reference by passing the pointer. -- This however, in the function is still passing the pointer by value. In C, none of the arguments of the function parameters are passed by reference. They are always passed by value. – Ilan Keshet Jun 27 '18 at 23:53
  • @IlanKeshet, as I said, you are arguing semantics. "Pass-by-reference" had a different meaning in the past than the one you understand. Yes, the pointer itself is being passed by value, but by dereferencing the pointer in the function, you have access to the REFERENCE that was passed. In other words, you can still modify the ORIGINAL object's value, even though only a COPY of the pointer was passed. – OregonJim Jun 29 '18 at 02:25

2 Answers2

4

C passes arguments by value, always, meaning that the called function receives a local copy of whatever the caller refers to.

The called function can modify the received value, because it is a local copy, without affecting the original value. For example:

char *test(char *s) {
  s++;
  return s;
}

t = test("A");

it's legal and shows that the parameter s can be modified without affecting the caller (which passes a literal...).

But the strcpy() of you example does something different: it takes a pointer s, and modifies what s points to. Pointers are powerful, and they can be used to simulate "pass by reference" (a pointer is a reference).

after assignment *s = *t is held, which one is compared with '\0'? *s or *t?

The *s: in C, an assignment returns a value - and the value is the value of the assigned variable after the assignment is done. Writing:

if (i=3) ...

is the same as

i=3;
if (i) ...

If i was a pointer the syntax would be different but the mechanism is the same, the assignment would "use" the pointer and the value of the whole assignment is used as expression to be evaluated in the test.

2

Many people consider that idiom to be something that’s neither call-by-value or call-by-reference. For what it’s worth, Kernighan and Ritchie’s The C Programming Language does call arrays and pointers in C “references,” although it uses only the term call-by-value and not call-by-reference. That usage seems to have gone out of fashion once C++ added a different language feature called references.

A function that accepts a pointer and dereferences it will generally compile to the same machine code as a function in a language with call-by-reference. One difference that is not merely the absence of syntactic sugar: if the pointer argument itself is not const, it is possible to reassign a new value to it and make it reference something else, which “call-by-reference” semantics do not allow. In a language with call-by-reference, you could not write s++ or t++ to make the function arguments reference different objects! (C strings are stored in such a way that you can add an offset to the pointer to obtain a substring, whereas most langauges store the length of the string in the first few bytes of its memory.) However, you can mostly think of a reference T& in C++ as equivalent to passing a T *const that is guaranteed not to be NULL, and that has an invisible asterisk in front of its name.

Davislor
  • 14,674
  • 2
  • 34
  • 49