C Strings (Arrays vs. Pointers)
- Strings as arrays:Before the
string
class, the abstract idea of a string was implemented with just an array of characters. For example, here is a string:char label[] = "Single";
------------------------------ | S | i | n | g | l | e | | ------------------------------
1000
.
Note: Don't forget that one character is needed to store the nul character (), which indicates the end of the string.
A character array can have more characters than the abstract string held in it, as below:char label[10] = "Single";
------------------------------------------ | S | i | n | g | l | e | | | | | ------------------------------------------
cout << "Third char is: " << label[2] << endl;
char label[] = "Single"; // 7 characters char label[10] = "Single";
- Strings as pointers:Another way of accessing a contiguous chunk of memory, instead of with an array, is with a pointer.
Since we are talking about strings, which are made up of characters, we'll be using pointers to characters, or rather,
char *
's. However, pointers only hold an address, they cannot hold all the characters in a character array. This means that when we use achar *
to keep track of a string, the character array containing the string must already exist (having been either statically- or dynamically-allocated). Below is how you might use a character pointer to keep track of a string.char label[] = "Single"; char label2[10] = "Married"; char *labelPtr; labelPtr = label;
label
started at memory address2000
, etc.):label @2000 ------------------------------ | S | i | n | g | l | e | | ------------------------------ label2 @3000 ------------------------------------------ | M | a | r | r | i | e | d | | | | ------------------------------------------ labelPtr @4000 -------- | 2000 | --------
Note: Since we assigned the pointer the address of an array of characters, the pointer must be a character pointer--the types must match.Also, to assign the address of an array to a pointer, we do not use the address-of (&
) operator since the name of an array (likelabel
) behaves like the address of that array in this context.
Now, we can uselabelPtr
just like the array namelabel
. So, we could access the third character in the string with:cout << "Third char is: " << labelPtr[2] << endl;
labelPtr
allows us to access thelabel
array is because we madelabelPtr
point to it. Suppose, we do the following:labelPtr = label2;
labelPtr
refer tolabel
, but now tolabel2
as follows:label2 @3000 ------------------------------------------ | M | a | r | r | i | e | d | | | | ------------------------------------------ labelPtr @4000 -------- | 3000 | --------
labelPtr
, we are referring to characters inlabel2
. The following:cout << "Third char is: " << labelPtr[2] << endl;
label2
array. - Passing strings:Just as we can pass other kinds of arrays to functions, we can do so with strings.
Below is the definition of a function that prints a label and a call to that function:
void PrintLabel(char the_label[]) { cout << "Label: " << the_label << endl; } ... int main() { char label[] = "Single"; ... PrintLabel(label); ...
label
is a character array, and the functionPrintLabel()
expects a character array, the above makes sense. However, if we have a pointer to the character arraylabel
, as in:char *labelPtr = label;
PrintLabel(labelPtr);
PrintLabel()
could have been written in two ways:void PrintLabel(char the_label[]) { cout << "Label: " << the_label << endl; } OR void PrintLabel(char *the_label) { cout << "Label: " << the_label << endl; }
Note: In C++, there is a difference in the use of brackets ([]
) when declaring a global, static or local array variable versususing this array notation for the parameter of a function.With a parameter to a function, you always get a pointer even if you use array notation. This is true for all types of arrays.
- Dynamically-allocated string:Since sometimes you do not know how big a string is until run-time, you may have to resort to dynamic allocation.
The following is an example of dynamically-allocating space for a string at run-time:
void SomeFunc(int length) { char *str; // Don't forget extra char for nul character. str = new char[length + 1]; ... // Done with str. delete [] str; ...
new
(the allocation operator) to give us back enough space for an array of the desired size. Operatornew
requires the type of elements (here,char
) and the number of elements needed (given as the array size between[
and]
). Note that unlike static allocation, e.g.:char name[20];
new
for allocation).We keep track of the dynamically-allocated array with a pointer (e.g., the return value of the call tonew
is stored instr
).We then can use that pointer as we used pointers to statically-allocated arrays above (i.e., we access individual characters withstr[i]
, pass the string to a function, etc.). Finally, note that when we are done using the string, we must deallocate it.
Note: Note the use of[]
when usingdelete
to deallocate an array.Here, we deallocate the string in the same function, but in some cases we might still need it afterSomeFunc()
ends, so we'd deallocate it later. Remember, we must keep a pointer to the beginning of the string because that's what is used to access the string and to deallocate it.
- Arrays vs. Pointers:As we can now see, there is more than one way to view a string. A string might be accessed in a statically-allocated array, it might be accessed via a pointer to a statically-allocated array, or perhaps via a pointer to a dynamically-allocated array.
BU CAS CS - C Strings (Arrays vs. Pointers) Copyright © 1993-2000 by Robert I. Pitts <rip at bu dot edu>. All Rights Reserved.