简体   繁体   中英

Casting dynamically allocated arrays of arbitrary pointers in ANSI C

This fairly straightforward snippet constructed out of a much larger body of code that gives the "warning: assignment makes integer from pointer without a cast [enabled by default]".

For simplicity I have even changed the caddr_t's to char *... in reality this is part of a set of routines that dynamically generate structures and in this case creates an array which may contain arbitrary pointers to arbitrary malloc'd structures. And left out the struct that the calloc'd array gets inserted into.

It's the way I did OO back in the 80's and I have a lot of code that works this way.

#include    <stdio.h>
#include    <stdlib.h>

int main(int argc, char* argv[]) {
  int n = 10;
  int i;
  char *p;

  p = (char *) calloc(n,sizeof(char *));
  for (i=0; i<n; i++) {p[i] = (char *) NULL;}
}

So is there an easy way to make a modern C happy or do I have to use a -W switch to tell it to just go away and not bother me?

And yes, I prefer a C that acts like a set of macro's for PDP-11 assembler ;-)

you should be declaring p as char ** p , if you want an array of pointers.

Then either remove the cast before calloc or cast it with ( char ** )

You're getting the warning because this statement:

p[i] = (char *)NULL;

Is assigning a pointer to an integer - p[i] is a char . To get this program to behave correctly, you'll want to change p to be char ** , rather than char * . That is - it should be an array of pointers to strings, not a pointer to an array of characters.

In addition, you can get rid of those typecasts and the parentheses in the sizeof operator.

char **p = calloc(n, sizeof *p);

And

p[i] = NULL;

Are a lot easier to read.

Even better, since the null pointer constant is almost certainly an all-zero bit pattern on your machine, you don't need the loop doing the assignment at all - the calloc call already zeroed out the memory for you.

Here's a simplified program that's semantically identical to yours, assuming that's the case:

#include <stdlib.h>

int main(void)
{
  int n = 10;
  char **p = calloc(n, sizeof *p);
}

The reason the compiler is upset is that you have:

char *p;

and then you are assigning pointers (char *)NULL to characters char at:

p[i] = (char *)NULL;

You should probably be using:

char **p = (char **)calloc(n, sizeof(char *));

but if you use calloc() , the subsequent loop is superfluous anyway (unless you're on a weird machine where the in-memory representation of a null pointer is not all bits zero, but then you should probably not use calloc() but simply use malloc() anyway).

There are those who excoriate the use of casts on malloc() and calloc() ; I'm not in that school, having worked on systems (pre-standard C) where the cast was necessary. I compile with options that ensure that my code doesn't run foul of the problems that those who excoriate casts are afraid of.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM