Thread: terminology - pointer to array of ... or just array of?

  1. #1
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658

    terminology - pointer to array of ... or just array of?

    Example:

    Code:
    char *aps[5] = {{"aps zero "}, {"aps one  "}, {"aps two  "},
                    {"aps three"}, {"aps four "}};
    For this example, using the debugger, aps is a pointer to the first of 5 pointers to the initial characters of 5 strings. If aps is placed in the "watch" window it shows up as char **aps, but expanding it will show exactly 5 pointers. (If the above code was char** aps = malloc(...), then the watch window would only show aps and expanding it would only show *aps.)

    My issue is the terminology for what aps is. In C / C++, the name of an array implies a pointer to the first element of that array, so that (*aps) == &aps[0];, so it seems that aps should be called an array of pointers (to the initial characters of strings).

    However some articles call aps a pointer to an array of pointers, but this would imply a second dereference is needed, since there would be one dereference for the pointer, and a second dereference for the array. (**aps) = &(*aps)[0]). This terminology seems to conflict with how C / C++ handles arrays when referenced by the name, such as passing the name of an array as a function parameter.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Round 2: Fight! >_<

    aps is a pointer to the first of 5 pointers to the initial characters of 5 strings
    No.

    Code:
    char *aps[5] = {{"aps zero "}, {"aps one  "}, {"aps two  "}, {"aps three"}, {"aps four "}};
    In that example code `aps' is an array of pointer to `char'.

    Code:
    void Go1(char ** faps); // `faps is a pointer to a location in memory which is a single pointer or an array of pointers
    void Go2(char ** faps); // `faps is a pointer to a location in memory which is a single pointer or an array of pointers
    // ...
    Go1(aps); // `aps' is an array but decays into a pointer to a pointer
    Go2(aps); // `aps' is an array but decays into a pointer to a pointer
    some articles call aps a pointer to an array of pointers
    They are wrong, or as with other examples you've quoted, you misunderstood that they are using meaningful but inaccurate descriptive language to explain something which may be unfamiliar to the target audience.

    this would imply a second dereference is needed
    Given your inability to understand this issue, I'm betting you also don't understand where the first "dereference" happens with a pointer to pointer or array or pointers.

    Code:
    char *aps[5] = {{"aps zero "}, {"aps one  "}, {"aps two  "}, {"aps three"}, {"aps four "}};
    // ...
    char * s = aps[0]; // `aps' is "dereferenced"
    Soma
    Last edited by phantomotap; 05-23-2013 at 05:48 PM.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by rcgldr View Post
    For this example, using the debugger, aps is a pointer to the first of 5 pointers to the initial characters of 5 strings. If aps is placed in the "watch" window it shows up as char **aps, but expanding it will show exactly 5 pointers. (If the above code was char** aps = malloc(...), then the watch window would only show aps and expanding it would only show *aps.)
    All that is happening here is that the debugger is expressing the fact that the name of an array is implicitly converted to a pointer. Even when describing an array as a pointer,it is keeping track of how many elements are in that array (at least, where that is known to the compiler, so it becomes known to the debugger).

    Quote Originally Posted by rcgldr View Post
    My issue is the terminology for what aps is. In C / C++, the name of an array implies a pointer to the first element of that array, so that (*aps) == &aps[0];, so it seems that aps should be called an array of pointers (to the initial characters of strings).
    Firstly, (*aps) is equivalent to aps[0], not to &aps[0]. (*aps) often has the same value as &aps[0], but always has different type.

    aps is defined as an array of pointers. That doesn't stop the compiler (or debugger in your case) making use of the concept that "array of X" is a type that can be implicitly converted into "pointer to X", and displaying information accordingly.


    Quote Originally Posted by rcgldr View Post
    However some articles call aps a pointer to an array of pointers, but this would imply a second dereference is needed, since there would be one dereference for the pointer, and a second dereference for the array. (**aps) = &(*aps)[0]). This terminology seems to conflict with how C / C++ handles arrays when referenced by the name, such as passing the name of an array as a function parameter.
    The problem is less with the terminology (which is pretty precise once one has succeeded in wrapping one's mind around it) and more with your lack of understanding of it.

    And, yes, some authors do get it wrong too, which is less than helpful for beginners. Some authors also gloss over some of the finer points, in order to teach ideas that work 99% of the time, even if they break down sometimes.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by rcgldr View Post
    using the debugger, aps is a pointer to the first of 5 pointers to the initial characters of 5 strings.
    Quote Originally Posted by phantomotap View Post
    No. In that example code `aps' is an array of pointer to `char'.
    You seemed to have missed the part "using the debugger ... " (as opposed to using C / C++ terminology). Using the debugger to look at memory at the machine language level, aps is a pointer to the first of 5 pointers. In my test debug run, aps = 0x419004, [0x419004] = 0x41777c, a pointer to the first string, [0x419008] = 0x41776c, a pointer to the second string, ... , [0x419014] = 0x41773c, a pointer to the fifth string.

    Again this seems to be an issue of semantics. At the machine language level, aps is a pointer to an array of pointers, but using C / C++ terminology, char *aps[] is an array of pointers.

    For the alternate form, char **aps, using C / C++ terminology, aps would be a pointer to a pointer which could be part of an array of pointers.

    On a side note, assuming an array of pointers, normally aps would point the the first pointer of an array, but if aps pointed to a pointer in the middle of an array of pointers, then a negative index such as aps[-1] would be valid.

    Quote Originally Posted by grumpy View Post
    (*aps) is equivalent to aps[0], not to &aps[0].
    You're correct. I meant to write

    aps == &aps[0] (this could be implementation dependent, as my compiler converts both to char **)

    and as you mentioned,

    (*aps) == aps[0]

    So getting back to the main point, the consensus here is that using C / C++ terminology, then calling either char *aps[] or char **aps a pointer to an array of pointers is incorrect.
    Last edited by rcgldr; 05-23-2013 at 07:09 PM.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by rcgldr View Post
    Again this seems to be an issue of semantics. At the machine language level, aps is a pointer to an array of pointers, but using C / C++ terminology, char *aps[] is an array of pointers.
    Sure. Why do you expect C/C++ terminology would be consistent with the terminology associated with any target system? Terminology in use varies between target systems (it is chosen differently by different vendors) so there is no way that the C/C++ standard could be consistent with all of them. C/C++ terminology only needs to be consistent within scope of C/C++, not with every target system.

    Quote Originally Posted by rcgldr View Post
    On a side note, assuming an array of pointers, normally aps would point the the first pointer of an array, but if aps pointed to a pointer in the middle of an array of pointers, then a negative index such as aps[-1] would be valid.
    Uh hum.

    Quote Originally Posted by rcgldr View Post
    So getting back to the main point, the consensus here is that using C / C++ terminology, then calling either char *aps[] or char **aps a pointer to an array of pointers is incorrect.
    It is more than a consensus. It is a fact in C/C++.

    Calling them that is incorrect, yes. Depending on context, it is correct to use them as if they are arrays of pointers.

    And learning about the contexts - where it is correct or not to use them as arrays of pointers - is probably what you need to do next to understand the advice (the pointers, even) that people have given you.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    (*aps) often has the same value as &aps[0]
    O_o

    Nope. That would only be true coincidentally or by purpose of some silly code.

    The `(*aps)' statement is "dereferencing" the `aps' variable which has the same value as the `aps[0]' statement because it too is "dereferencing" the `aps' variable.

    The `(&aps[0])' statement "dereferences" the `aps' variable and immediately "takes the address of" the "dereferenced" variable so has the same value as `(aps)' which does have a different type because `aps' is an array of pointer to `char' while `(&aps[0])' has decayed into a pointer to a pointer to `char'.

    I am sure that was just just a typo; I just wanted to stomp on it before rcgldr runs off in the wrong direction quoting it as has so many books and articles.

    Again this seems to be an issue of semantics.
    Nope. You obviously just don't understand.

    At the machine language level, aps is a pointer to an array of pointers, but using C / C++ terminology, char *aps[] is an array of pointers.
    At the machine language level all variables which aren't in registers are in some form of memory referenced by a register, instruction, or pointer. If we assume that `aps' is a stack variable, the stack or stack pointer is adjust by some means which sets aside a contiguous block of memory of `sizeof(char *) * 5' bytes allowing us to address the array by virtue of the stack pointer such as `stack_pointer - 20' for `aps[0]'. This style of addressing does not in any way change what `aps' is, which is an array, or how we interpret it, an array of pointers. We could consider the `int' stack variable--from (`int i;')--`i' in the same terms by way of `stack_pointer - 24', but `i' is absolutely not a pointer to `int'.

    Soma
    Last edited by phantomotap; 05-23-2013 at 07:48 PM.

  7. #7
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by rcgldr View Post
    (*aps) == &aps[0];
    Quote Originally Posted by phantomotap View Post
    Nope.
    This was corrected in post #4:

    Quote Originally Posted by rcgldr View Post
    I meant to write
    aps == &aps[0] (this could be implementation dependent, as my compiler converts both to char **)
    and as you mentioned,
    (*aps) == aps[0]

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    This was corrected in post #4:
    O_o

    Wow.

    You just don't pay attention to anything at all do you?

    I was pointing out that grumpy made a typo when he was explain this to you.

    *shrug*

    I'm done; you don't pay enough attention to what people have told you to be worth the time people have put in explaining this to you over this fifteenth occasion.

    Soma

  9. #9
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by phantomotap View Post
    You just don't pay attention to anything at all do you?
    It would help if you didn't remove the poster's names from your quotes.

  10. #10
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    An example program. aps0 is a global array of pointers, while aps1 is an allocated pointer to pointer. For this program, (void *)aps0 == (void *)&aps0, but (void *)aps1 != (void *)&aps1. &aps1 is the address of a location in memory (probably on the stack) that contains a pointer to the first pointer of an array of pointers.

    Code:
    #include <iostream>
    
    using namespace std;
    
    char *aps0[5] = {{"aps0 zero "}, {"aps0 one  "}, {"aps0 two  "},
                     {"aps0 three"}, {"aps0 four "}};
    
    int main(int argc, char *argv[])
    {
        int i;
        char **aps1 = (char **) malloc(5*sizeof(char *));
    
        aps1[0] = "aps1 zero ";
        aps1[1] = "aps1 one  ";
        aps1[2] = "aps1 two  ";
        aps1[3] = "aps1 three";
        aps1[4] = "aps1 four ";
    
        for(i = 0; i < 5; i++)
            cout << aps0[i] << ' ' << aps1[i] << endl;
    
        free(aps1);
    
        return(0);
    }

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by rcgldr View Post
    For this program, (void *)aps0 == (void *)&aps0...
    Yes, because aps0 decays to a pointer to the first element in the array, and &aps0 is the address of the array, which again is to where the array begins. Same address, but different types.

    but (void *)aps1 != (void *)&aps1.
    Obviously, since aps1 is a char**, so you get the address of that variable on the stack, which is of type char***.

    &aps1 is the address of a location in memory (probably on the stack) that contains a pointer to the first pointer of an array of pointers.
    On the stack.

    But what is your point here?
    Also, why do you keep using char* and malloc when you explicitly put this in C++? If you're going to use C++, then do it; otherwise, why post in the C++ section?
    Also using char* for string literals is bad practice; you should use const char* (refers to both C and C++).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Elysia View Post
    why do you keep using char* and malloc when you explicitly put this in C++?
    I wanted to cover both C and C++, since this originally was related to argv in main(), which is declared as char * argv[], in the K&R C book, and defined as char **argv in the C++ standard.

    Quote Originally Posted by Elysia View Post
    Also using char* for string literals is bad practice; you should use const char* (refers to both C and C++).
    This was just an example program, in this case the strings were literals, but I wanted to cover the more general case where the strings may not be literals.

    The main point of posting that example program was to show the difference between a global array of pointers (aps0), versus an allocated pointer to the first pointer of what could be an array of pointers (aps1). Although the two variables, aps0, and aps1 are different, the syntax for using either one can be the same, aps0[] or aps1[].

  13. #13
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by rcgldr View Post
    Again this seems to be an issue of semantics. At the machine language level, aps is a pointer to an array of pointers, but using C / C++ terminology, char *aps[] is an array of pointers.
    No, you're still wrong.
    At any level it is just an array of pointers. In assembly, you have to obtain the memory location that the array starts at in order to do somthing with the array, but that action doesn't inherrently change what the array is.

    It's just like how a regular global int variable isn't a pointer to an int, it's just an int. If you want to read the value that int contains, then yes the compiler likely needs to use the information it has about where the variable was placed to generate assembly instructions that contain the address where the variable was located. Once it has that address, through that it can perform a read. That address doesn't actually exist in the program unless the compiler generates the code for it. Claiming the int itself is a pointer is just plain wrong, and it's no different from what you are arguing.

    It's like how you are yourself, you are not your name. The fact that someone has to call your name to get your attention doesn't change that. The array is just the array, and there is no spoon.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by rcgldr View Post
    The main point of posting that example program was to show the difference between a global array of pointers (aps0), versus an allocated pointer to the first pointer of what could be an array of pointers (aps1). Although the two variables, aps0, and aps1 are different, the syntax for using either one can be the same, aps0[] or aps1[].
    I am losing track of what you actually are trying to argue about. Are you trying to say that argv is an array of pointers? That it can be an array of pointers? That arrays and pointers to first element are just two different ways of referring to the same language feature?

    We know that both pointers and arrays support the indexing operator.
    We both know that an array declared in some function is an array.
    We also know that, unless you pass that array by reference, to a function, it will decay into a pointer to the first element and the actual formal argument in the function is a pointer to the first element.
    Global arrays are not immune to this when passed into a function. When accessed directly, however, they do not suffer from decay similarly to local arrays.
    It doesn't get any more trivial than this.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Elysia View Post
    I am losing track of what you actually are trying to argue about. Are you trying to say that argv is an array of pointers?
    Not in this thread. I only mentioned argv since I was asked why I used char * and malloc. The point of this thread was to question articles that call char *aps[], "a pointer to an array of pointers", as opposed to just "an array of pointers".

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. deleting pointer array of pointer array
    By rodrigorules in forum C++ Programming
    Replies: 3
    Last Post: 02-09-2010, 05:36 AM
  2. Replies: 7
    Last Post: 05-11-2008, 10:57 AM
  3. Replies: 19
    Last Post: 07-20-2007, 01:46 AM
  4. sizeof pointer-to-array -- &array
    By josemariasola in forum C Programming
    Replies: 19
    Last Post: 07-15-2006, 06:39 PM
  5. Pointer Terminology Question
    By SourceCode in forum C Programming
    Replies: 2
    Last Post: 03-07-2003, 09:11 AM