-2
#include    <stdio.h>

char**      StringArray ( int n_size )
{
    char*   astr_allocate[ n_size ];
    char**  pstr_string_array = astr_allocate;
    int n_count;

    for ( n_count = 0; n_count < n_size; n_count++ )
        *(pstr_string_array + n_count) = " ";

    *(pstr_string_array + n_size) = "\0";

    return  pstr_string_array;
}


char*       String      ( int n_size )
{
    char    ach_allocate[ n_size ];
    char*   str_string = ach_allocate;
    int n_count;

    for ( n_count = 0; n_count < n_size; n_count++ )
        *(str_string + n_count) = ' ';

    *(str_string + n_size) = '\0';

    return  str_string;
}


void main ()
{

    int n_size      = 5;
    int n_count     ;
    char*   pch_string  = String ( n_size );
    char**  pstr_string = StringArray ( n_size );

    for ( n_count = 0; n_count < n_size; n_count++ )
        printf  ( "%c", *(pch_string + n_count) );

    for ( n_count = 0; n_count < n_size; n_count++ )
        printf  ( "%s", *(pstr_string + n_count) );

    printf  ( "\n\n" );
}

This produces wonderful outputs of "???" (Literal question marks) and random stuff like that. I am just trying to understand pointers and string type stuff more, if someone could help out that would be great thankyou!

additionally: Been writing and compiling this in a linux terminal and nano, if that changes anything

user3502489
  • 361
  • 1
  • 4
  • 11
  • 2
    This invokes **a lot** of undefined behaviour, off-by-one errors, and a lot of other stuff. – 3442 Sep 17 '15 at 05:25
  • To begin with, an array of arrays is *not* the same as an pointer to pointer (see e.g. [this old answer of mine](http://stackoverflow.com/questions/18440205/casting-void-to-2d-array-of-int-c/18440456#18440456) for an explanation of why). Secondly, you still return a pointer to a local variable, which goes out of scope once that function returns. – Some programmer dude Sep 17 '15 at 05:27
  • Oh okay I see what you are talking about, how would you make that work though? also .. I found out if I only use one of the functions, they work but when I make the array and the string array, then it craps itself, how does that make a difference? – user3502489 Sep 17 '15 at 05:33
  • Undefined behavior is undefined, there's really no more to say. However, practically the memory used by the local variables still exists in the state it were when the function returned, which is why it *seems* to work when calling the function just once, however calling *any* other function will most likely reuse that memory for the new function call. – Some programmer dude Sep 17 '15 at 05:37
  • As for a solution, search for and read about *dynamic memory allocation* (and read about the [`malloc`](http://en.cppreference.com/w/c/memory/malloc) and [`free`](http://en.cppreference.com/w/c/memory/free) functions). – Some programmer dude Sep 17 '15 at 05:38
  • that makes sense .. yes I know about malloc and free, but I've always wanted to know how they work and be able to manipulate it myself, which I know isn't just what I've done, so is there any books/ documentation or anything you can suggest to learning that stuff? – user3502489 Sep 17 '15 at 05:42
  • You don't really need to know how they work, just that `malloc` allocates memory and `free` frees it. The memory itself can be treated like an array in most cases (but you can't use `sizeof` to get the size), and just like an array is a contiguous space of memory. Also worth noting is that using `malloc` you allocate a specific number of *bytes* and not elements, so if you want to allocate 10 pointers to `char` then you need to do e.g. `10 * sizeof(char *)`. – Some programmer dude Sep 17 '15 at 05:50
  • Oh, and to help you with some of your other problems, the expression `*(some_array_or_pointer + X)` is equivalent to `some_array_or_pointer[X]`, and that will hopefully help you understand why `*(pstr_string_array + n_size) = "\0"` write out of bounds in your array. – Some programmer dude Sep 17 '15 at 05:54
  • Its just something I've always wanted to know, I get annoyed at not knowing how something works or not being able to make it myself. I know its not the most useful skill but is there anyway you know how I could learn how those functions work and/or make my own? Yes I know the [] operators, I've just been trying different things, trying to understand it all – user3502489 Sep 17 '15 at 05:59

1 Answers1

1

I would recommend that you study arrays, pointers and strings more.

  • Since this program is a program for a regular hosted system (Linux), you must declare main as int main (void).
  • C does not have a pre-made string class, C strings are arrays of characters. As such they need to actually be allocated somewhere. You do try to allocate them as local variables inside a function, but you cannot return a pointer to a local variable, as that variable will cease to be valid once you leave the function. The memory which was previously reserved for your array may now be used for completely unrelated things at any time. See this.
  • Arrays in C are zero-indexed. Meaning that given an array int arr[2]; the items have index [0] and [1]. Therefore you can't access it as arr[2] = ... or *(arr + 2) = ..., because that points past the end of the array.
  • Given a pointer to character, which points at an array of characters (C string), you can't assign data to it by doing things like *(pstr_string_array + n_count) = " "; because that will only change where the pointer points at! You copy nothing. Instead, you must use strcpy(pointer, " ", 2).
  • A string literal " " is the same as an array of characters char arr [2] = {' ', '\0'}. So code like "\0" doesn't make any sense.
  • Pointers to pointers are not arrays, nor do they point to arrays, nor are they compatible with arrays. There is a lot of incorrect books and tutorials out there teaching blatantly incorrect uses of pointer-to-pointer. There's actually very few cases where you need to use it, 2D arrays is not one of them, so just forget you ever saw pointer-to-pointer for now.
  • Please note that *(pointer + n) is 100% equivalent to pointer[n]. The latter is easier to read, so use that form when possible.
Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thankyou very much! This clears some stuff up which is great! I've got the basic concept of arrays, but that definitely helped. I have always been interesting in trying to find out how prebuilt functions work (why I don't just want to use malloc and free ), which was what I was attempting to have a go at there ^.. the reason why I wanted a char**, was in another simple game program I made, was to remake it, and add a log file, which holds an array of everything that happens, which would be an array of string logs, but I think I'll try writing to a file instead for that, seem easier haha – user3502489 Sep 17 '15 at 13:16