2

Say I want to read in a list of pages name of max 19 character, e.g. 4 (Number of page) Name1 Name2 Name3 Name4

I am trying to use a global 2D array to store the page number and page name, I got an error saying assignment from incompatiable pointer type...

Thanks

static int nPages;
static char** pageName;

int main(void){
  scanf(" %d", &nPages);

  pageName = (char *)malloc(nPages*sizeof(char));
  for(int i=0; i < nPages ;i++){
    pageName[i] = (char *)malloc(20*sizeof(char));
    scanf(" %s", pageName[i]);
  }

//Free Memory Here of coz. 

  return 0;
}
Jono
  • 23
  • 3

5 Answers5

5

Never cast the return value of malloc() in C. It hides compiler warnings that actually help you, and it's never necessary so it just adds clutter. You should use:

pageName = malloc(nPages * sizeof *pageName);

Note how this is free from repetitions of the type name of pageName. Here, sizeof *pageName means "the size of the object pointed at by pageName", i.e. "the size of a character pointer". You should expect a sizeof expression as malloc()'s argument very often.

Also, sizeof (char) is always 1 in C, so that particular expression, it can be argued, adds more clutter than it helps make the code safe.

Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
3

The problem lies right there:

pageName = (char *)malloc(nPages*sizeof(char));

pageName is a char **, not a char *. So it should read:

pageName = malloc(nPages*sizeof(char*)); // sizeof(char *), and no need to cast

EDIT: removed the cast

Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
  • Thanks but how would the char length of max 19 be expressed in this case ? – Jono May 11 '11 at 14:11
  • Whoops, i get it, thats just for the first malloc. Thanks =] – Jono May 11 '11 at 14:12
  • 2
    Because I disagree with what "it should read". I don't like casts in my mallocs. – R. Martinho Fernandes May 11 '11 at 14:29
  • @Martinho Sorry about that, I'm primarily a C++ programmer. – Etienne de Martel May 11 '11 at 14:32
  • @Etienne: changed to +1. FWIW, this is one of those situations that shows that C isn't strictly a subset of C++. Without the cast, it won't compile in C++. – R. Martinho Fernandes May 11 '11 at 14:38
  • C++ programmers using `malloc` and casting the result is roughly as offensive as English speakers using words from other languages and botching the pronunciation or meaning... :-) – R.. GitHub STOP HELPING ICE May 11 '11 at 15:57
  • 1
    @R.. I prefer using `new`, but whenever I have to write C and I have to use `malloc`, I can't help but say "oh, this returns a `void *`, better cast it, because implicit conversions are _evil_." – Etienne de Martel May 11 '11 at 17:07
  • On the other hand, explicit conversions are evil. They're a red flag that you're doing something you shouldn't be doing. The C language has exactly (well, almost exactly) the right set of implicit conversions so that you never need to make them explicit when you're doing something reasonable. – R.. GitHub STOP HELPING ICE May 11 '11 at 17:11
0

Your defined pageName as char ** but when calling malloc to initialize the pointer, you use a cast to (char *). Maybe that is the problem.

Constantinius
  • 34,183
  • 8
  • 77
  • 85
0

You are assigning char* to char** at your first malloc line. Just drop the (char*) cast - C handles void* to char** conversion automatically.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
0

char* and char** are two different types, and you can't freely assign the first to the latter.

Having said that, you have to do a two-step initialization. First, you have to malloc() space for nPages string:

pageName = (char**) malloc(nPages * sizeof(char*));

then, you have to malloc() space for each pageName:

for (i = 0; i < nPages; ++i) {
    pageName[i] = (char*) malloc(20);
}
Simone
  • 11,655
  • 1
  • 30
  • 43