Pointers and Arrays in C

T

Terence

I usually program in Java, so I am a bit confused about usint pointers in C.
I would really appreciate if someone can help me.

Case 1:
======

// Is this function no good? Since str is a variable created on stack,
// I am assuming it will be deallocated immedately after the function returns,
// right??
char * generateString()
{
char str[100] = "abc";
return str;
}

Case 2:
=====

// str is a pointer pointing to a literal
// Can I use str just like other char arrays?
// How are memory allocated for literals and when are they deallocated??
void main()
{
char * str;
str = "abc";
}

Case 3:
=====

// Similar to case 2 except the literal is returned from a function
// Again, can I use str for anything? When is it deleted from memory??
void main()
{
char * str;
str = generateString();
}

char * generateString()
{
return "abc";
}

Case 4:
=====

// assigning dynamically allocated array to pointer
void main()
{
char * str;
str = generateString();
...
delete str; // I have to delete str at the end, Right?
}

char * generateString()
{
char * charArray = new char[20];
strcpy(charArray, "abc");
return charArray;
}

Case 5:
=====

// str points to a char array created in a C library function
// How was this char array allocated? When will it be deallocated?
// Do I have to delete it explicitly??
void main()
{
char line[20] = "abc#def";
char * str;

str = strtok(line, "#");

delete str; // is this necessary?
// can I modify the content of the array??
}
 
A

Artie Gold

Terence said:
I usually program in Java, so I am a bit confused about usint pointers in C.
I would really appreciate if someone can help me.

Case 1:
======

// Is this function no good? Since str is a variable created on stack,
// I am assuming it will be deallocated immedately after the function returns,
// right??

You are fundamentally correct (it may or not actually be
*deallocated* but it no longer logically exists once the block in
which it is declared is exited).
char * generateString()
{
char str[100] = "abc";
return str;
}

Case 2:
=====

// str is a pointer pointing to a literal
// Can I use str just like other char arrays?
// How are memory allocated for literals and when are they deallocated??
void main()

Say it with me:
main() returns int main() returns int main() returns int
{
char * str;
str = "abc";
}

A literal exists for the life of the program. The mechanism is
irrelevant (and an issue for the implementation). It may not be mutable.
Case 3:
=====

// Similar to case 2 except the literal is returned from a function
// Again, can I use str for anything? When is it deleted from memory??
void main()
{
char * str;
str = generateString();

Yes -- but don't try to change it.
}

char * generateString()
{
return "abc";
}

Case 4:
=====

// assigning dynamically allocated array to pointer
void main()

Say it with me:
main() returns int main() returns int main() ...
{
char * str;
str = generateString();
...
delete str; // I have to delete str at the end, Right?
}

char * generateString()
{
char * charArray = new char[20];
strcpy(charArray, "abc");
return charArray;
}
Correct.


Case 5:
=====

// str points to a char array created in a C library function
// How was this char array allocated? When will it be deallocated?
// Do I have to delete it explicitly??
void main()
{
char line[20] = "abc#def";
char * str;

str = strtok(line, "#");

delete str; // is this necessary?

Not only unnecessary -- but doing so would invoke undefined
behavior, likely resulting in a crash (but only if you're lucky; the
other possibilities are considerably more frightening).
// can I modify the content of the array??

Yes you can. Be aware, however, that strtok alters what its first
argument points to -- so what `str' points to might surprise you.
Reaed whatever documentation is available at least twice before
using strtok().

HTH,
--ag
 
D

Dave Vandervies

I usually program in Java, so I am a bit confused about usint pointers in C.
I would really appreciate if someone can help me.

If you haven't already, go read the FAQ at
http://www.parashift.com/c++-faq-lite/

This will probably answer a lot of your questions faster than waiting for
a reply on the newsgroup, though a quick look to refresh my memory didn't
find anything about a few of these (the ones about string literals).


Case 1:
======

// Is this function no good? Since str is a variable created on stack,
// I am assuming it will be deallocated immedately after the function returns,
// right??

That's correct. str goes away when generateString returns, and the
pointer to it that you're returning becomes invalid.
char * generateString()
{
char str[100] = "abc";
return str;
}

Case 2:
=====

// str is a pointer pointing to a literal
// Can I use str just like other char arrays?

Almost; you can't modify it, but otherwise, yes. (So you can treat it
exactly like you would treat any other array of const char.)
// How are memory allocated for literals and when are they deallocated??

They are allocated before the program starts and deallocated after it
ends, so any pointer you have that points at a string literal will be
valid anywhere you use it.
void main()

main always returns int in both C and C++.
(Hmm, you said you're coming from Java, didn't you? Excuse me for
a minute while I go poke my sigmonster with a pointy stick... There,
that's better.)
{
char * str;
str = "abc";
}


Case 3:
=====

// Similar to case 2 except the literal is returned from a function
// Again, can I use str for anything? When is it deleted from memory??

Yes. What you're returning is a pointer to the first element in the
array represented by the string literal; unlike the array on the stack
in case 1, this will still be there when generateString returns.
void main()
{
char * str;
str = generateString();
}

char * generateString()
{
return "abc";
}

Case 4:
=====

// assigning dynamically allocated array to pointer

This is almost correct.
Aside from the void main that I've noted elsewhere, you also have a
mismatched new/delete; memory allocated with "new type[size]" needs to
be deallocated with delete[], not plain delete.

But yes, you do have to deallocate the memory you allocated in
generateString when you're done with it. Every new needs a matching
delete.

void main()
{
char * str;
str = generateString();
...
delete str; // I have to delete str at the end, Right?
}

char * generateString()
{
char * charArray = new char[20];
strcpy(charArray, "abc");
return charArray;
}

Case 5:
=====

// str points to a char array created in a C library function
// How was this char array allocated? When will it be deallocated?
// Do I have to delete it explicitly??

Using strtok for this is a bad example, because it works on the string
you give it and doesn't create a copy for you, so in your example you
don't need to deallocate str (since it points into memory that will be
deallocated for you when the function returns) and you can modify it
(as long as you don't step outside the bounds of your 20-element array).
In fact, I don't know of any C library functions (besides the obvious
malloc and friends) that allocate memory for you, so I'm not sure your
question as asked makes sense.

If your question referred to strdup (a unixism that copies a string
into memory obtained from malloc), the answer would be that you need to
release that memory by passing the pointer you got from strdup to free()
when you're done with it.
More generally, if you're using a library function (whether it's from the
standard library or another library) that allocates resources, you need
to find out how those resources were allocated and how you're expected
to release them when you're done with them.
void main()
{
char line[20] = "abc#def";
char * str;

str = strtok(line, "#");

delete str; // is this necessary?
// can I modify the content of the array??
}


dave
 
D

Dave Vandervies

Dave Vandervies said:
Yes. What you're returning is a pointer to the first element in the
array represented by the string literal; unlike the array on the stack
in case 1, this will still be there when generateString returns.

Before the pedants[1] start beating me over head for this, the "stack"
I'm referring to is the function-invocation stack. This is typically
implemented using a hardware stack, but anything that "looks stack-like"
at the granularity of all-the-automatic-variables-in-a-function is a
valid way of doing it.


dave

[1] CLC++ *does* have pedants, I hope? CLC would be far less interesting
(and far less informative) without them, and I assume that the same
goes for here.
 
D

Dave Vandervies

Dave said:
Yes. What you're returning is a pointer to the first element in the
array represented by the string literal; unlike the array on the stack
in case 1, this will still be there when generateString returns.

Before the pedants[1] start beating me over head for this, the "stack"
I'm referring to is the function-invocation stack. This is typically
implemented using a hardware stack, but anything that "looks
stack-like" at the granularity of all-the-automatic-variables-
in-a-function is a valid way of doing it.

Couldn't an implementation even choose to dynamically allocate the
automatic variables internally and when they go out of scope, delete
them again? Not the fastest solution, but valid AFAIK.

Yep, it would be valid, but you'd still end up with something that looks
stack-like; the first function invoked (or, more precisely, the first
scope entered) would be the bottom of the stack, and the most recent one
would be the top. When you enter a scope, you create a new invocation
record and push it onto the stack; when you leave, you pop and discard
the record at the top, and return to the scope represented by the next
record down.

[1] CLC++ *does* have pedants, I hope?

I thought all the regulars are pedants, aren't they?

I would be worried if they weren't.


dave
 
R

Rolf Magnus

Terence said:
I usually program in Java, so I am a bit confused about usint pointers
in C.

If your question is about C, you should ask in a C newsgroup instead of
one about C++. Your questions however mostly apply to C as well as C++.
I would really appreciate if someone can help me.

Case 1:
======

// Is this function no good? Since str is a variable created on
stack,
// I am assuming it will be deallocated immedately after the function
returns,
// right??
char * generateString()
{
char str[100] = "abc";
return str;
}

The C++ standard doesn't require it to be stored on a stack. Anyway,
it's an automatic variable that is destroyed when it goes out of scope,
which happens when you return from the function. So you must not use
the returned pointer outside the function. Thus, I'd rather say that
the memory is deallocated immediately before the function returns or
exactly at the moment when it returns. The important part is just that
you cannot use it outside the function.
Case 2:
=====

// str is a pointer pointing to a literal
// Can I use str just like other char arrays?
// How are memory allocated for literals and when are they
deallocated?? void main()
{
char * str;
str = "abc";
}

A literal exists for the whole life time of the program, so you can use
a pointer to it even outside the function. You can't use it like "other
char arrays", because you may not write to it. The reason why it's
allowed to let a pointer to non-const point to it is historical (a
legacy from C).
Btw: main must return int.
Case 3:
=====

// Similar to case 2 except the literal is returned from a function
// Again, can I use str for anything? When is it deleted from
memory?? void main()
{
char * str;
str = generateString();
}

char * generateString()
{
return "abc";
}

Just as above, the literal exists as long as the program is running, so
you're free to use it anywhere, but again, you must not write to it.
Better let generateString return a const char*, so you can't by
accident write to it.
Case 4:
=====

// assigning dynamically allocated array to pointer
void main()
{
char * str;
str = generateString();
...
delete str; // I have to delete str at the end, Right?
}

char * generateString()
{
char * charArray = new char[20];
strcpy(charArray, "abc");
return charArray;
}

That's almost correct. If you use new, you need a corresponding delete.
If you use new[], you need delete[], so your last line of main would
need to be:

delete [] str;
Case 5:
=====

// str points to a char array created in a C library function
// How was this char array allocated? When will it be deallocated?
// Do I have to delete it explicitly??
void main()
{
char line[20] = "abc#def";
char * str;

str = strtok(line, "#");

delete str; // is this necessary?
// can I modify the content of the array??
}

strtok doesn't allocate any memory. It modifies the char array you gave
to it.
Generally, look into the documentation of a function. It should always
tell you whether you have to deallocate any memory from it or not.
 
R

Rolf Magnus

Dave said:
Yes. What you're returning is a pointer to the first element in the
array represented by the string literal; unlike the array on the stack
in case 1, this will still be there when generateString returns.

Before the pedants[1] start beating me over head for this, the "stack"
I'm referring to is the function-invocation stack. This is typically
implemented using a hardware stack, but anything that "looks
stack-like" at the granularity of all-the-automatic-variables-
in-a-function is a valid way of doing it.

Couldn't an implementation even choose to dynamically allocate the
automatic variables internally and when they go out of scope, delete
them again? Not the fastest solution, but valid AFAIK.
[1] CLC++ *does* have pedants, I hope?

I thought all the regulars are pedants, aren't they?
 
P

Peter van Merkerk

< snipped questions about pointer and C-style string handling>

Other have answer your questions already. But since you are asking the
questions in comp.lang.c++ and you are new to C++ (I presume), you might
be interested in the std::string class. The std::string class makes
string handling much easier and less error prone compared to C style
strings; no need to worry about pointers, life time issues, allocating
sufficient memory...etc. Also string manipulation is much more
convenient with this class:

#include <iostream>
#include <string>
using namespace std;

string generateString(string name)
{
string str = "Hello " + name + "!";
return str;
}

int main()
{
cout << "Your name ? ";
string name;
getline(cin, name);
string msg = generateString(name);
cout << msg << endl;
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top