0

Here is my program :

#include <cstring>
const int SIZE =10; 

int main() 
{ 
    char aName [SIZE]; // creates an array on the stack
    std::strcpy(aName, "Mary");
    return 0;
}

This program is obviously useless, I am just trying to understand the behavior of the strcpy function.

Here is it's signature : char * strcpy ( char * destination, const char * source )

so when I do : std::strcpy(aName, "Mary");

I am passing by value the variable aName. I know that the aName (in the main) contains the address of the array. So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?

I am asking this because it is very confusing to me. Whenever I have encountered addresses it usually was to point to a memory allocated on the heap...

Thanks!

trincot
  • 317,000
  • 35
  • 244
  • 286
CSstudZ
  • 101
  • 10
  • I dont' know if I understand your question correctly. A pointer can point anywhere, not just to the heap. if you want to know, where string literals are stored, you might find [this question](https://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-memory) helpful. – Lukas-T Dec 16 '19 at 17:16

6 Answers6

1

Whenever you encounter addresses it doesn't mean it will always point to memory allocated to heap.

You can assign the address of a variable to a pointer like this

int a=5;
int *myPtr= &a;

Now, myPtr is a pointer of type integer which points to the memory of variable which is created on stack which is a have value 5.

So, whenever you create a pointer and assign the (address of) memory using new keyword, it will allocate the memory on heap. So, if I assign the value like this it will be on stack

int *myPtr= new int[5];
M Hamza Razzaq
  • 432
  • 2
  • 7
  • 15
1

So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?

Yes.

Whenever I have encountered addresses it usually was to point to a memory allocated on the heap...

Yep, usually. But not always.

Pointers to non-dynamically-allocated things are fairly rare in C++, though in C it's more common as that's the only way to have "out arguments" (C does not have references).

strcpy is a function from C's standard library.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

Function parameters are its local variables.

In this call

std::strcpy(aName, "Mary");

the two arrays (one that is created in main with the automatic storage duration and other is the string literal that has the static storage duration) are implicitly converted to pointers to their first elements.

So you may imagine this call and the function definition the following way

std::strcpy(aName, "Mary");

 // …

char * strcpy ( /* char * destination, const char * source */ )
{
    char *destination = aName;
    const char *source = "Mary";

    // …

    return destination;
}

Or even like

char *p_to_aName = &aName[0];
const char *p_to_literal = &"Mary"[0];
std::strcpy( p_to_aName, p_to_literal );

 // …

char * strcpy ( /* char * destination, const char * source */ )
{
    char *destination = p_to_aName;
    const char *source = p_to_literal;

    // …

    return destination;
}

That is within the function its parameters are local variable of pointer types with the automatic storage duration that are initialized by pointers to first characters of the passed character arrays

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Maybe it would help to look at an example implementation of strcpy():

char* strcpy(char* d, const char* s)
{
    char* tmp = d;

    while (*tmp++ = *s++)
        ;

    return d;
}

That's really all there is to it. Copy characters from the source to the destination until the source character is null (including the null). Return the pointer to the beginning of the destination. Done.

Pointers point to memory. It doesn't matter if that memory is "stack", "heap" or "static".

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
0

So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?

Yes. That is correct. Though I probably wouldn't call it a local variable. It is a parameter. Local variable usually means something like this:

int localVariable;

The word'parameter" is often associated with things like this:

int myFunction(int parameter) {
    // use parameter some where...
}

The point is roughly the same though: it creates a variable that will go out of scope once the function exits.

I am asking this because it is very confusing to me. Whenever I have encountered addresses it usually was to point to a memory allocated on the heap...

Yes, this is the most common use case for them. But it isn't their only use. Pointers are addresses, and every variable has an address in memory regardless of whether it is allocated on the "heap" or "stack."

The use here probably because pointers to a char are commonly used to store strings, particularly on older compilers. That combined with the fact that arrays "decay" into pointers, it is probably easier to work with pointers. It is also certainly more backwards compatible to do it this way.

The function could have just as easily used an array, like this:

char * strcpy ( char destination[], const char source[ )

But I'm going to assume it is easier to work with pointers here instead (Note: I don't think you can return an array in C++, so I'm still using char *. However, even if you could, I would imagine it is still easier to work with pointers anyway, so I don't think it makes a lot of difference here.).


Another common use of pointers is using them as a way to sort of "pass by reference":

void foo(int * myX) {
    *myX = 4;
}

int main() {
    int x = 0;

    foo(&x);

    std::cout << x; // prints "4"

    return 0;
}

However, in modern C++, actually passing by reference is preferred to this:

void foo(int & myX) {
    myX = 4;
}

int main() {
    int x = 0;

    foo(x);

    std::cout << x; // prints "4"

    return 0;
}

But I bring it up as another example to help drive the point home: memory allocated on the heap isn't the only use of pointers, merely the most common one (though actually dynamically allocated memory has been mostly replaced in modern C++ by things like std::vector, but that is beside the point here).

  • In the declaration `char * strcpy ( char destination[], const char source[] )` both `destination` and `source` are pointers. In almost all contexts, the name of an array decays into a pointer to its first element. So that function declaration means exactly the same thing as `char * strcpy ( char *destination, const char *source )`. This is a common source of confusion for newcomers. – Pete Becker Dec 16 '19 at 22:32
  • Could you give me a source to back that up? It's not that I think you're wrong, but would like to read a more in-depth explanation to make sure I understand properly.. –  Dec 16 '19 at 22:35
  • Google “array to pointer decay”. You’ll find a bunch of stuff. – Pete Becker Dec 16 '19 at 22:44
  • I mean, I did and found [this](https://stackoverflow.com/q/1461432/10957435) which already has a place in my answer. So perhaps I'm still not understanding what you mean. –  Dec 16 '19 at 22:54
  • @PeteBecker To be pedantic, It isn't technically directly because of the decaying why `char destination[]` is equal to `char* destination` in an argument declaration, right? It is because of the complementary rule of type adjustment. The array type is adjusted to be the pointer type in the argument declaration. @Chipster It's really unclear why you "assume it is easier to work with pointers here instead" considering that you are working with pointers regardless of which type you declare (because it will be a pointer after the adjustment either way). – eerorika Dec 17 '19 at 00:25
  • @eerorika My question is, are you working with pointers regardless? The syntax is only subtly different here, but different nonetheless. Arrays and pointers are not the same thing, though very similar. If you have a source explaining that it gets converted to a pointer here, I'm certainly more than willing to change it. I just need a source that I can read up on to make sure I properly understand why it is get converted here. I can't articulate a correction to something I don't understand how I got wrong. –  Dec 17 '19 at 00:52
  • As to why it's easier, possibly to work better with older systems. I know a lot of C code works with pointers, not arrays. My reasoning here is that the committee likes to make sure that old code doesn't break as much as possible. But my reasoning could be wildly flawed and very wrong. Please let me know if it is. –  Dec 17 '19 at 00:53
  • @Chipster Arrays and pointers are not the same thing. But arrays cannot be passed to functions by value. You can declare an argument to be an array, but it is adjusted to be a pointer. `char*` and `char[]` and `char[N]` all declare exactly the same type of argument: pointer to `char` but only in an argument declaration, because of the adjustment rule - without the adjustment they would be different types. The distinction of the syntaxes is so subtle that it is only meaningful to the programmer: declaring an array implies that the pointer will be used as an iterator. – eerorika Dec 17 '19 at 01:06
  • For reference, see [dcl.fct] section of the standard and search for "adjusted". Personally, I prefer to never declare function argument to be an array, because type adjustments confuse beginners. But it's purely a matter of style and there are advantages to declaring array arguments (that are still actually pointers). – eerorika Dec 17 '19 at 01:06
0

I know that the aName (in the main) contains the address of the array.

You knew wrong. aName is an array. It contains the elements, not an address.

But when you use the name of the array as a value such as when passing it to strcpy, it is implicitly converted to a pointer to first element of the array (the value of a pointer is the memory address of the pointed object). Such implicit conversion is called decaying.

So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?

This is correct enough. To clarify: It is a function argument rather than a local variable. But the distinction is not important here. Technically, it is the caller who is responsible for pushing the arguments onto the stack or storing them into registers, so it could be considered that main "creates" the variable.

Whenever I have encountered addresses it usually was to point to a memory allocated on the heap

Pointers are not uniquely associated with "heap". Pretty much any object can be pointed at, whether it has dynamic, static or automatic storage or even if it is a subobject.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • But if aName does not contain the adress of the array. How come strcpy still accepts it as an argument if strcpy's arguments are pointers (therefore there values are adresses)? – CSstudZ Dec 16 '19 at 18:08
  • @CSstudZ Because of the implicit conversion. – eerorika Dec 16 '19 at 18:09
  • Implicit conversion of an array means taking an array as an argument and using it's address ? – CSstudZ Dec 16 '19 at 18:10
  • @CSstudZ In C++ some values can be implicitly converted from one type to another. For example, if there is a function that accepts an `int` , you can pass a `5.2` into the function, then the value will be implicitly converted to the type `int` and the converted value will be 5. This is an implicit conversion. Similarly, if a function accepts a pointer to `char`, and you pass an array of 10 `char` instead, then there is an implicit conversion. The array will be converted to pointer to char, and the converted value will be address of the first element. – eerorika Dec 16 '19 at 18:14