views:

218

answers:

6

I have a homework assignment with a number of questions. One is asking why the strcpy() function doesn't need the call by reference operator for CStrings. I've looked through the book numerous times and I can't, for the life of me, find the answer. Can anyone help explain this to me?

It is an array of sorts so I would think you would need the call by reference.

+1  A: 

Well in the case you mean c-strings (char*) you don't need a call by reference because the string itself is a pointer. So string copy knows where to/from where to copy the string.

Simon
That's not entirely correct, the string might not be a pointer. The string can be an array of chars. See my answer below.
piotr
+3  A: 

strcpy() takes a pointer to char.

Thus you don't pass the "string" as a parameter but only the address of its first character.

So basically you have something like this:

void func(const char* str);

const char* str = "abc";
func(str); // Here str isn't passed by reference but since str is a pointer to the first character ('a' here), you don't need a reference.

Passing a pointer is fast. On a 32 bits architecture, a pointer takes 32 bits, whatever the length of the pointed string.

ereOn
A: 

Because strcpy works with char* which are pointers. The pointer is passed by value, and strcpy uses that pointer to access the indiviual characters in the target string and change them. Compare that to passing an integer by value - the function can't change the original integer.

Understanding how char* strings are not like integers is vital to you not going crazy during your C++ course. Well done for your prof making you face it.

Kate Gregory
A: 

Because in C when calling functions, arrays are passed as the address of the first element, which is equivalent of calling by reference.

See Peter Van Der Linden Expert C programming, Deep secrets book.

piotr
+2  A: 

If you mean class CString, then in other words the question asks you:

Why does this compile?

CString sExample;
char buffer[LARGE_ENOUGH];

strcpy(buffer, sExample);

The answer is, because class CString defines an operator const char* and therefore can be converted to the type of strcpy's second argument.

I 'm not sure if this is what you mean though.

Jon
+2  A: 

This a problem of terminology, mostly.

An "object" (I use the term as designing "a chunk of RAM") is passed by value when the called function gets a copy of the chunk. It is passed by reference when the called function gets a way to access the one and only chunk.

Consider this:

void f(int x)
{
    x = 42;
}

void g()
{
    int y = 54;
    f(y);
    // here "y" still has value 54
}

Here, the function f() modifies x, but that is its own x, a variable which contains a copy of the contents of the y variable of g(). What f() does with its x does not impact what the y of g() contains. The variable is then passed by value.

C++ has a notion of reference which goes like this:

void f(int& x)
{
    x = 42;
}

void g()
{
    int y = 54;
    f(y);
    // here "y" now has value 42
}

Here, the special construction (with the "&") instructs the C++ compiler to play some hidden tricks so that the x known by f() is actually a kind of alias on the y variable used by g(). There is only one variable: the x and the y designate the same chunk of RAM. The variable is here passed by reference.

Now, consider a "C string". In C (and C++), a string is just a bunch of char values, the last of which having value 0 (this is the conventional string terminator). The code does not handle strings directly; it uses pointers. A pointer is a value which actually designates an emplacement in RAM. The pointer is not the string; the pointer is a kind of number (usually on 32 or 64 bits, it depends on the processor type and the operating system) which tells where in RAM is the first char of the string. So when you call strcpy() you actually give it pointers (one for the destination buffer, one for the source string). Those pointers are unmodified: the source string and the destination buffers are not moved in the process; only the contents of the string are copied into the destination buffer.

Hence, strcpy() needs not have access to the variables which contain the pointers in the caller code. strcpy() only needs to know where the destination buffer and the source strings are in RAM. Giving a copy of the pointer values to strcpy() is enough. Hence, those pointers are passed by value.

Note that in the presence of pointers, there are two objects to consider: the variable which contains the pointer, and the chunk of RAM which is pointed to. The pointer itself is passed by value (strcpy() receives its own copy of the variable which contains the pointer to the destination buffer). We can say that the pointed-to chunk of RAM (the destination buffer) is "passed by reference" since it is not duplicated in the process and the called function (strcpy()) can modify it. The point here is that the term "reference" has two distinct meanings:

  • The C++ syntax meaning: "reference" designates the special construction with the "&" that I have described above.

  • The language theory formal meaning: "reference" designates a way by which a value is indirectly designated, so that caller and callee may access the same chunk of RAM under distinct names. With that meaning, passing by value a pointer to a called function is equivalent to passing by reference the chunk of RAM to which the pointer points.

A C++ "reference" (first meaning) is a syntaxic way to pass "by reference" (second meaning) a variable.

Thomas Pornin