4

So its been a while since I took courses on c and c++ and I'm curious on c pointers (im going to use the new keyword in my examples even thought I know malloc is the C way). I always recall my teacher always forcing us to use pointer, she would never take assignments with arrays, she proved to us that there are less commands needed in assembly language when you used pointers rather then used arrays. I want to continue this good practice but I seem to be struggling to use pointers, specifically double pounter.

Lets say I want to create a word bank without using the c++ string datatype and I have a double pointer of type char.

int main()
{
   string fileName = "file.txt";
   char** wordBank = null;
   int wordCount = countWords(fileName); //somefunction to get word count
}

Now I need to allocate a memory space big enough for the entire bank But im unsure on how to do this I believe it is somthing like this?

wordBank = new char*[wordCount];

now I need to allocate space specifilly for the size of each word, which i am still unsure aobut.

for(int i = 0; i < wordCount; i++)
{
   wordLength = getWordLength(fileName, i); // some function to get word length of each...
   //... word in the bank
   (*wordBank) = new char[wordLength];
}

Okay the last part I'm confused about is passing double pointers through functions. lets say I have a function that lets me manipulate a an entire word, lets say I want to just pass the word, what would I pass through the function call and what would the function definition have. And lets say I want to pass the entire bank and a number that will move the pointer, what would I pass through the function call and what would the function definition have. Sorry for all the questions usually If I try to answer these things by myself by writing short programs but I'm having difficulty just getting it to compile. I appreciate the responses I receive.

user1314272
  • 141
  • 1
  • 13
  • 2
    I try to stay away from mixing `*` and `[]`. – motoku Apr 02 '14 at 04:16
  • `wordBank[i] = new char[wordLength]` ? – angdev Apr 02 '14 at 04:19
  • 1
    I know you said in the question that you didn't want to, but if you're using C++ (as indicated by the `new` keyword) then I'd *really, really strongly recommend* using `std::string`. There is no good reason not to in this case. It will take care of all the memory management for you, you won't have to worry about nul terminators, and it will be no less efficient than doing all the allocation and copying yourself. Your `wordBank` array would be better as a `std::vector` as well. Again, it's no less efficient, but much easier and safer to use. – Tristan Brindle Apr 02 '14 at 05:03
  • Less commands doesn't necessarily mean better performance. Look up "premature optimization". I wouldn't think of this concept as good practice, but rather the opposite. Believe me when I say that when you use `new` or `malloc` everywhere you will spend much more time worrying about what went wrong with your program than you actually save in performance. – Excelcius Apr 02 '14 at 05:24

2 Answers2

8

To allocate the bank:

wordBank = malloc(wordCount * sizeof(char *));

To allocate individual words:

char *addWord(char **wordBank, size_t idx, char *word) {
  wordBank[idx] = malloc(strlen(word) + 1);
  // this is how you pass a word
  strcpy(wordBank[idx], word);
  return wordBank[idx];
}

// how you pass the wordBank:
addWord(wordBand, index, someWord);

But having more instructions in the assembly is not necessarily bad. A constant overhead is generally not a problem in programming. I would use std::string and std::vector<string> and spend my time on real problems. At least not on debugging mallocs and frees, assigning and testing NULL pointers.

perreal
  • 94,503
  • 21
  • 155
  • 181
  • amen to using `std::string` and `std::vector`... but in your example wouldn't it be better to use new instead of malloc? – jsantander Apr 02 '14 at 04:26
  • Pehaps better in C++, but then it doesn't even make sense to use new/delete :) – perreal Apr 02 '14 at 04:28
  • If you've got Posix, then `wordBank[i] = strdup(word)` is a little shorter – Tristan Brindle Apr 02 '14 at 05:10
  • Can I give an extra upvote for the last paragraph? :) – Excelcius Apr 02 '14 at 05:20
  • +1 for the last paragraph. In addition, the difference in assembly language between array and pointer access tends to be simple arithmetic. Even if the code does need to be optimized, it generally takes changes in cache misses and/or unpredictable conditional branches to make much difference. – Patricia Shanahan Apr 02 '14 at 05:44
1

My take:

wordBank = new char*[wordCount];

This is fine: you're allocating an array of wordCount elements of char*

for(int i = 0; i < wordCount; i++)
{
   wordLength = getWordLength(fileName, i); // some function to get word length of each...
   //... word in the bank
   wordBank[i] = new char[wordLength];
}

As it has been indicated in the comments (@angdev), for each item in the array (of char *) we need to allocate memory.

One word os caution is that you must remember to deallocate that memory when done... and that you should deallocate with the right operation for the allocation you did:

  • if you used malloc() ---> use free()
  • if you used new ---> use delete`
  • if you used new [] ---> use delete []`

Finally, if you need to modify a pointer inside a function, use a reference to a pointer:

char *myPointer=0;

fillIt(myPointer);

So... if you want fillIt() to actually modify where myPointer points, the function should be:

void fillIt(char * & p) { ... }

Alternatively you can define it as:

void fillIt(char ** p) { ... }

and invoked it as

char *myPointer=0;

fillIt(&myPointer);
jsantander
  • 4,972
  • 16
  • 27