0

I want to have array of poiners to array of chars... (weird, I know, but I can't use STL lib) So I've declared it as : const char *** DbRecord; DbRecord = new const char**[1000];

And then I've got this function:

 bool AddToArray(const char* value,
        const char *** database);

how to store pointer to that const char * value to my DbRecord on position [0] ? And how to access it then to be able to read the value, which is actually saved there and not the pointer? I'm really confused about about pointers in C++ :-/ Thanks for the explanation...

Martin Dvoracek
  • 1,714
  • 6
  • 27
  • 55

3 Answers3

1

how to store pointer to that const char * value to my DbRecord on position [0] ?

You can't, because value will go out of scope once the function ends.

Do you really need three stars? It seems to me two should be sufficient:

const char** DbRecord;
DbRecord = new const char*[1000];

void AddToArray(const char* value, const char** database)
{
    database[0] = value;
}
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • I must use `***` because it's homework for practicing algorithmization and I'll have to sort and search the array frequently, so array of pouinters would be much faster then array of values. – Martin Dvoracek Apr 09 '13 at 20:26
  • Are you implying that a `const char**` is faster than a `const char*`? Because it most certainly isn't. All object pointers are of the same size. – fredoverflow Apr 09 '13 at 20:27
  • 1
    @Dworza You definitely need to [get a good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Etienne de Martel Apr 09 '13 at 20:29
  • Nope.. I will have records like : id, name, adress, city ...Nevertheless for example city will have only a few unique records so it would be good to make only pointers to those values... So I need `char*` to store the actual value beacuse I can't use `string`, then another `*` to create array of those chars and the third one `*` to have pointers to those array indexes? Am I right? – Martin Dvoracek Apr 09 '13 at 20:30
  • If you have one C string "London", then you can have as many `char*`s to it as you want. You only pay one machine word for each. If you insist on storing `char**`s instead, you also pay one machine word for each `char**`, but you also have to pay one additional machine word for that single shared `char*`. So with `char**` you end up with more memory and more dereferencing. – fredoverflow Apr 09 '13 at 20:33
  • 1
    Note that for `string`s, assignment means copying of the underlying char array, whereas for `char*`s, assignment means sharing of the char array. When you go from `string` to `char*` and you want sharing, you don't need that extra `*`, because `char*` already has the desired "sharing semantics". Makes sense? – fredoverflow Apr 09 '13 at 20:40
1

DbRecord is an array of pointers that points to const char **, so when you say DbRecord[0] it really means the first row of a 3D char array, which elements are of const char** type. So DbRecord[0][0] = value will store the variable value at index row [0][0] if this is what you want.

When you allocate memory for DbRecord, only doing

DbRecord = new const char**[1000];

is not enough, you have to set size of the other two dimensions.

You can try to use std::string to replace const char * and vector<vector<string>> to replace const char *** in C++, in which case, you don't need to worry about those pointers anymore.

taocp
  • 23,276
  • 10
  • 49
  • 62
  • as I've said - I am very limited on imports... I can't use `string` and `vector` as well... that's why I want to create that awful structure `char ***` – Martin Dvoracek Apr 09 '13 at 20:32
1

Ok. You asked your question simple enough. :)

I want to have array of poiners to array of chars...

You're on the right track. At the very least that is char *[]. However, as we all know, that can easily be translated to char **. Of course, to have a pointer to the storage, you need to add the third star. You're correct so far in your question.

how to store pointer to that const char * value to my DbRecord on position [0]

Well there are two ways to do it. The correct answer to the question the way you asked it is to dereference the pointer. For example:

bool AddToArray(const char* value,
    const char *** database)
{
    bool success = false;
    ((*database)[0]) = value;
    if ( (*database)[0] == value ) success == true;
    return success;
}

Technically, accessing a pointer as an array will also dereference it as an index. So the [0] there will dereference the pointer straight. Depending on how you lay out your allocations and memory, you could also do it like this:

...
(*(database[0])) = value;
...

Note the subtle difference there. Where the first example treated it as a pointer to an array of pointers (or a pointer to an array of arrays, depending on how you think of it), this second example treats it as an array of pointers to an array (or an array of pointers to pointers).

Learning to master multiple levels of pointers is one of the best things you can do as a C developer but it's generally a frowned-upon practice in C++.

Hope this helps.

Edit: char *[] not char [][]

inetknght
  • 4,300
  • 1
  • 26
  • 52
  • There is no such thing as `char [][]` in either C or C++. – fredoverflow Apr 09 '13 at 20:43
  • 1
    That's funny, it compiles just fine in g++ with -pedantic – inetknght Apr 09 '13 at 20:49
  • [No it doesn't](http://ideone.com/FCkLdX): `error: declaration of ‘a’ as multidimensional array must have bounds for all dimensions except the first` – fredoverflow Apr 09 '13 at 20:50
  • @inetknght: Even if it did, that would be irrelevant, as there's a fine chance that it's just an extension. – Puppy Apr 09 '13 at 20:54
  • Technically I'm wrong in that it's a double array so incorrect for the answer; I'll edit that for correction. But it's valid construct. http://pastebin.com/FNkhPa7d I'm sure you can see where I was wrong. – inetknght Apr 09 '13 at 20:56