1.11M Members

arrays & pointers

 
0
 

I have been told that in C++ the concept of a string does not exist. A string is just an array of type char. So in the following code, is message an array because it doesn't really look like one?

char *message = "I am having trouble understanding pointers";
std::cout << message

The line above does not really resembel an array to me, is this just a short way of saying
char *array[] = "some stuff";

I'M also confused by the line char *members[4] = {"Sally", "Alex", "George", "Martha"};
I thought that the number in the [] of a char array would dictate how many characters are in the array but in this case it's how many strings all together. What have I missed here.

Lastly, I can write a very very small pointer program that changes the value of x and then cout << x and accuratly predict the output but anything more compicated than that I'M completly lost. I don't understand the relationship between pointers and arrays nor do I understand any pointer that begins with more than one *. Thanks for any and all help.

 
3
 

So in the following code, is message an array because it doesn't really look like one?

Yes. The string literal is actually stored as and has a type of array to const char. When used in value context it evaluates to a pointer to the first element, which is why you can assign it to a pointer. It's also a holdover from C that you can assign a pointer to const char (in this context) to a pointer to char, which would normally be illegal without a cast.

To be strictly correct, any pointers to a string literal should have a type of const char* because string literals are technically supposed to be read-only.

I thought that the number in the [] of a char array would dictate how many characters are in the array but in this case it's how many strings all together. What have I missed here.

You're storing an array of pointers, the size of the array dictates how many pointers the array can hold, which in this case is 4. It helps to think of int instead of the pointer to char aspect is confusing you:

int members[4] = {1, 2, 3, 4};

The fact that the array holds pointers to char, which can be the first element of a string is irrelevant to how the array works. You need to understand the pointer to char as a string and array concepts separately, then combine them without mixing them up.

I don't understand the relationship between pointers and arrays nor do I understand any pointer that begins with more than one *.

An array is not a pointer and a pointer is not an array. A pointer can point into an array. An array name in value context is converted to a pointer to the first element. Other than that, they're best reated as completely separate and independent.

Please read C for Smarties.

 
1
 

Any* is an array of items of type Any (and use const char* in your examples, otherwise most compilers will complain). In effect, it is a pointer to the first element of the array, so that Any++ will point you to the next element in the array.

An array of pointers, such as Any* many[5], points to an array of arrays of Any items. Your example of const char* members[4] = {"Sally", "Alex", "George", "Martha"}; is such.

So, cout << array << endl; will output the line

some stuff

and cout << members[0] << endl; will output the line

Sally

If you do this:

cout << ++array << endl

you get

ome stuff

but if out do this:

cout << ++members << endl

you get

Alex

That is because in the last case, you are moving the pointer to the next member in the array of pointers, and in the previous case you are moving the pointer to the next member in that array of chars. Clear as mud, right! :-)

 
1
 

Anyway, you posted an excellent question for newbie C/C++ programmers, and an area that a lot get wrong. Keep on trucking! :-)

 
3
 

I have been told that in C++ the concept of a string does not exist. A string is just an array of type char.

Yes and no. At the fundamental level, a string is just a sequence of characters, and in that sense, an array of characters. This is the case in all programming languages, some expose that directly, others hide it in a standard library feature, and others hide it in a language feature.

In C, creating and manipulating strings is done through the creation and manipulation of an array of char, terminated by a null-character (i.e., usually called a "null-terminated C-style string"). C++, like any other C-inspired language, inherited that from C, however, the C++ standard library has a class called std::string (from header <string>) that hides away all these annoying details of the creation and manipulation of an array of char, and exposes much more convenient and rich functionality than raw arrays of char. So, the answer to your question is that the "concept" of a string is not embedded in the C++ language, but there is a standard string class that takes care of that. In practical terms, whether the language has strings as a language feature (e.g., Delphi or Java) or as a standard library feature on top of a more "low-level" representation as an array of char (e.g., C#, C++/CLI, Python, etc.), the difference is negligible. And in that sense, "does the concept of a string exist in C++?", yes, as much as in any other language.

So in the following code, is message an array because it doesn't really look like one?

To be precise, it is a local fixed-size array of char that has decayed to a pointer to a char.

If you write this:

int arr[4] = {1, 2, 3, 4};
// or, equivalently:
int arr[]  = {1, 2, 3, 4};

you are creating a local fixed-size array of integers, with size of 4. This is exactly the same as creating 4 integer local-variables one after the other, but with the convenience that you can address each of them with an integer index from 0 to 3. When it comes to a string literal (between quotes), the situation is very much the same except for that addition of the null-terminating character:

char s[5] = "1234";
// or, equivalently:
char s[]  = "1234";

this creates a local fixed-size array of characters, with size of 5, because it contains 4 valid characters and the null-terminating character. In other words, this is equivalent to:

char s[5] = {'1', '2', '3', '4', '\0'};

That's it, it's just a normal array with the addition of this null-terminating character.

Now, the last little piece of this is the decay to a pointer. The line separating an array from a pointer to the first element of the array, is a very fine line because arrays will decay to a pointer very easily in C or C++. If you write this:

int *arr = {1, 2, 3, 4};

It will not work because C++ doesn't allow the initialization of a pointer with a fixed-array, it will demand that you first create the array with int arr[] = {1,2,3,4};, and then you take a pointer to its first element (decay the array), as in int* parr = arr;.

In the other hand, for character arrays (e.g., char *s = "1234";), there is an exception to this rule as it creates a local fixed-size array of characters, and it immediately creates a pointer variable that points to the first element of that array. And that's really all there is to it, the decay occurs directly, but any good compiler should warn out about it. The warning will usually say that converting a literal string to a char* is bad (or deprecated), because usually a string literal is used in a read-only context, in which case it will decay to the pointer type const char*, and converting it to a char* is unusual (and requires a "hidden" construction of a local fixed-size array, and that makes the compiler feel dirty, it doesn't like to construct things you didn't explicitely ask it to construct).

It's that simple. It is easy to get confused by pointers and arrays because some people mistake them for the same thing, but it's just because arrays convert very quickly, easily, and often to a pointer to the first element.

The line above does not really resembel an array to me, is this just a short way of saying
char *array[] = "some stuff";

No, it is equivalent to:

char array[] = "some stuff";  // array of char. (no star)

I'M also confused by the line char *members[4] = {"Sally", "Alex", "George", "Martha"};

That is an array of 4 pointers to char (char*). Just like int a[4]; is an array of 4 integers, char* a[4]; is an array of 4 char-pointers. In the expression that initializes this array, there are a number of string literals, i.e., {"Sally", "Alex", "George", "Martha"}. This is no different than before, each string literal creates a local fixed-size char-array (with null-terminating char) and is then decayed to a pointer to the first char, and then those 4 pointers are assembled into a local fixed-size array of 4 char-pointers. If you really wanted to spell it out, it would be something like this:

// create local char-arrays:
char a1[] = "Sally";
char a2[] = "Alex";
char a3[] = "George";
char a4[] = "Martha";

// grab pointers to the first element of these arrays:
char* p1 = a1;
char* p2 = a2;
char* p3 = a3;
char* p4 = a4;

// collect the pointers into a local char-pointer array:
char* members[4] = {p1, p2, p3, p4};

I thought that the number in the [] of a char array would dictate how many characters are in the array but in this case it's how many strings all together. What have I missed here.

If there is not number number appearing within the square brackets [], then it means one of two things. If it appears in a declaration with an initializer, as so:

int arr[] = {1, 2, 3, 4};

then it just means that the size of the array is deduced from the initializer, in this case, the deduced size is 4, i.e., it is equivalent to int arr[4] = {1,2,3,4};. This is just for convenience of being able to add things in that initializer without having to count how many there are to update the number between the brackets.

If, on the other hand, the empty brackets [] appear in a declaration without an initializer, as in int arr[]; or as in void some_function(int arr[]), then the syntax is equivalent to int* arr;, in other words, it's a pointer, not an array. Personally, I, like others, wished that this confusing "feature" would not exist, but it is inherited from C and is kept for backward compatibility.

Lastly, I can write a very very small pointer program that changes the value of x and then cout << x and accuratly predict the output but anything more compicated than that I'M completly lost. I don't understand the relationship between pointers and arrays nor do I understand any pointer that begins with more than one *.

Arrays and pointers are confusing at times, and annoying to work with most of the time. The good news is, you don't have to work with them very often. For strings, use the standard class std::string, there are only rare occasions where you would need to work with arrays of chars directly (unfortunately, many C++ books waste an inordinate amount of time on the subject of char-arrays (C-style strings), to the point that some are convinced that C++ programmers are always using them, we don't, unless we interact with a C-style API). For other arrays, use standard STL containers such as std::vector, these are much nicer to use and hassle-free.

For pointers with more than one star, don't panic, just take the time to disect the declaration. A pointer variable is declared like <type> * varname; where <type> is the type of the object pointed-to by this pointer. The type of varname is <type>*, which is a pointer-type. Now, <type> can be anything, including another pointer type like int* or char*, leading to int** varname; or char** varname;, meaning that varname is a pointer to a pointer to an int or char, respectively. That's all. If int arr[4]; is an array of 4 integers, then int* arr[4]; is an array of 4 pointers to integers. Once you understand how these declarations embed into each other, and that a pointer type is just another variable type like int or double, it all becomes quite clear.

 
0
 

You you please give me a VERY simple example on using more than one star * with a pointer so I can better understand it and see how it might be useful? And by simple I mean as close to hello world as you can get so I don't have anything else consusing me or throwing me off. Thanks all, you've been very helpful.

 
3
 

Here's something, I hope it's not too complicated:

#include <iostream>

int main() {

  // create an array of C-style strings (const char*):
  const char* messages[] = {"Hello World!", "The answer is 42.", "Because the bold man told you so."};

  int selection_index = 0;
  std::cout << "Select the message you want displayed (0-2): ";
  std::cin >> selection_index;

  // declare a pointer to a C-style string, (or a pointer to pointer to const-char)
  // set the selection pointer to point to the string that was selected:
  const char** selection = &messages[selection_index];  
  // or, equivalently:
  // selection = messages + selection_index;

  std::cout << (*selection) << std::endl;

  return 0;
};

If the expression &messages[selection_index] confuses you, here's the explanation. Doing messages[selection_index] gives you the selection_index element from the messages array of const-char pointers, so, the resulting type of that expression is const char*. Then, the ampersand & takes the address of that element, and thus, returns a pointer to that pointer, i.e., it has the type const char**.

The alternative expression, which is messages + selection_index, is a bit simpler. In this case, the messages array decays to a pointer to the first element of the array, and so, it has the type const char**. Then, adding an integer to a pointer has the effect of moving the pointer by that integer amount, resulting in this case to a pointer to an element selection_index positions beyond the first element of the messages array. In other words, the result is the same as for &messages[selection_count].

The expression (*selection) dereferences the pointer. So, since selection has type const char**, when you dereference it, you get something of type const char*, which is a C-style string that you can print on std::cout.

I know that this is an ugly and contrived example, but there aren't too many simple and clean examples of uses of pointers to pointers, because they are inherently unusual and used in unusual situations, and are especially rare in C++ (compared to C).

Question Answered as of 1 Year Ago by mike_2000_17, rubberman, deceptikon and 1 other
 
0
 

Thanks everyone and thanks mike for the program. I'M going to go compile that right now.

You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article