Allocation of memory for Array of Pointers

S

smartbeginner

main()
{
int i;
int *a[2];
a=calloc(4,sizeof(*a));
/* The above code I know will not compile[Lvalue required] .But why
cant I allocate space
for all 4 integers i need to store */
for(i=0;i<2;i++)
a=calloc(2,sizeof(*a));
/* this works fine I know?But why not the earlier one */
}
 
C

chandan

Hi,
The reason might be:
You are trying to assign int * to int ** in the frist statement
however, in second stmt you are assigning int * to int * which is a
valid statement.

-Chandan
 
J

jamesonang

void *calloc(size_t nelem, size_t elsize)

function calloc return a pointer to a space suitably aligned for
storage of any type of objec.

a is a pointer to a integer , but a is a pointer to a space which is
a pointer to a integer.
 
M

moosdau

smartbeginner said:
main()
{
int i;
int *a[2];
a=calloc(4,sizeof(*a));
/* The above code I know will not compile[Lvalue required] .But why
cant I allocate space
for all 4 integers i need to store */
for(i=0;i<2;i++)
a=calloc(2,sizeof(*a));
/* this works fine I know?But why not the earlier one */
}


I think you really should go reading the section6 of comp.lang.c FAQ,
http://c-faq.com/aryptr/index.html
as you'v been suggested.

a is an array, a is a pointer.
they are not the same at all.
 
C

chandan

Forgot to mention that u must typecast the calloc function as its
return type is void * (however some compiler automatically return
pointer type of the type_of_its_second_ argument.)
 
A

Anand

chandan said:
Forgot to mention that u must typecast the calloc function as its
return type is void * (however some compiler automatically return
pointer type of the type_of_its_second_ argument.)
The standard calloc *always* returns void*. And you do not need the
cast. Read through the FAQ and numerous old posts in the archive as to
why you don't need a cast.

You did quote in your previous reply... you forgot here.
FYI: <http://cfaj.freeshell.org/google/>
Also see the welcome note about bottom posting.
 
K

Keith Thompson

chandan said:
Forgot to mention that u must typecast the calloc function as its
return type is void * (however some compiler automatically return
pointer type of the type_of_its_second_ argument.)

No. calloc() returns a result of type void*, but it's implicitly
converted to the target pointer type. An explicit cast is unnecessary
and can mask errors (such as forgetting the required "#include <stdlib.h>"
or compiling C code with a C++ compiler).

Please read <http://cfaj.freeshell.org/google/>, and don't use silly
abbreviations like "u" for "you".
 
M

Martin Ambuhl

chandan said:
Forgot to mention that u must typecast the calloc function as its
return type is void * (however some compiler automatically return
pointer type of the type_of_its_second_ argument.)

This is simply a pile of manure. Casting the return value from
calloc(), malloc(), or realloc() is unnecessart and serves only to hide
errors.

*All* confoming library implementations will return void * (_never_ the
type of an argument), and that void * pointer will seamlessly be
converted to a pointer to the appropiate type.

Pay no attention to chandon; he knows nothing.
 
A

Antonio Contreras

smartbeginner said:
main()
{
int i;
int *a[2];

The above sentece declares a as an array of two pointers to integers,
which I think it's not what you want.
a=calloc(4,sizeof(*a));

Now you try to assign a pointer to an array, sth that cannot be done.
As you said an Lvalue is required in the left side of an assignment,
and an array identifier is not an Lvalue.
/* The above code I know will not compile[Lvalue required] .But why
cant I allocate space
for all 4 integers i need to store */
for(i=0;i<2;i++)
a=calloc(2,sizeof(*a));
/* this works fine I know?But why not the earlier one */
}


I think that what you wanted to do was something along the lines of:

#include <stdlib.h>

int main (void) {
int (*a)[2]; /*Declare a as a pointer to an array of two integers*/
a = malloc(2 * sizeof(*a));
return 0;
}
 
J

John Bode

smartbeginner said:

Implicit typing of main() is no longer supported in the latest
standard, so start using either

int main(void)

or

int main(int argc, char **argv)
{
int i;
int *a[2];
a=calloc(4,sizeof(*a));
/* The above code I know will not compile[Lvalue required] .But why
cant I allocate space
for all 4 integers i need to store */

You have declared a as a 2-element array of pointers to int; as such,
you don't need to allocate any memory for a itself.

You're getting the error because a is an array type, not a pointer
type, and array type objects are not modifiable.

Secondly, how are you going to store 4 items into a 2-element array?
for(i=0;i<2;i++)
a=calloc(2,sizeof(*a));
/* this works fine I know?But why not the earlier one */
}


Because each element of a is a pointer type.

It would really help if you would explain exactly what you're trying to
do here. You're obviously confused about something, but without
knowing what you're trying to accomplish, I'm not sure I can help.

It sounds like you're trying to allocate 2 arrays of 2 elements each.
If that is the case, here are a couple of ways to do it:

/* First method */

#include <stdlib.h>

int main(void)
{
int **a;

/*
* Allocate enough memory to hold two int * objects
*/
a = calloc(2, sizeof *a); /* or malloc(2 * sizeof *a); */
if (a)
{
int i;
for (i = 0; i < 2; i++)
{
/*
* Allocate enough memory to hold two int objects
*/
a = calloc(2, sizeof **a); /* or malloc(2 * sizeof **a);
*/
if (a)
{
/* assign a[0] and a[1] */
}
else
{
printf("Memory allocation failed for a[%d]\n", i);
}
}
}
else
{
printf("Memory allocation failed for a\n");
}
return 0;
}

/* Second method */

#include <stdlib.h>

int main(void)
{
int (*a)[2];

a = calloc(2, sizeof *a); /* or malloc(2 * sizeof *a); */
if (a)
{
int i;
for (i = 0; i < 2; i++)
{
/* assign a[0] and a[1] */
}
}

return 0;
}
 
C

Chuck F.

chandan said:
Forgot to mention that u must typecast the calloc function as
its return type is void * (however some compiler automatically
return pointer type of the type_of_its_second_ argument.)

Please do not top-post, do not use silly confusing abbreviations
(such as "u" and the ilk), and do include context.

In addition your advice is wrong. There is never any need to cast
the return values from calloc, malloc, and friends. There IS a
need to #include the appropriate header, such as stdlib.h.

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
A

alice

smartbeginner said:
main()
{
int i;
int *a[2];
a=calloc(4,sizeof(*a));
/* The above code I know will not compile[Lvalue required] .But why
cant I allocate space
for all 4 integers i need to store */
for(i=0;i<2;i++)
a=calloc(2,sizeof(*a));
/* this works fine I know?But why not the earlier one */
}


The First one won't compile because a is an array and is NOT a pointer.
 
C

Charles Richmond

Chuck F. said:
Please do not top-post, do not use silly confusing abbreviations
(such as "u" and the ilk), and do include context.
....and do *not* generally be an asshole in any other way. ;-)
In addition your advice is wrong. There is never any need to cast
the return values from calloc, malloc, and friends. There IS a
need to #include the appropriate header, such as stdlib.h.
True, you don't need the cast. But if you are stubborn, the cast
is *not* prohibited by the C standard. ;-)
 
C

chandan

i said:
Forgot to mention that u must typecast the calloc function as its
return type is void * (however some compiler automatically return
pointer type of the type_of_its_second_ argument.)

i am sorry for the silly abbreviations, i had used. Thanks, for the
advice.

Martin said:
Pay no attention to chandon; he knows nothing.

I never told that i know everything. i am a beginner to C and, really,
i don't know anything, as such, about C. I got my first lesson and I am
eager to learn more.
No. calloc() returns a result of type void*, but it's implicitly
converted to the target pointer type. An explicit cast is unnecessary
and can mask errors (such as forgetting the required "#include <stdlib.h>"
or compiling C code with a C++ compiler).

In my case, i was trying to compile this code with a C++ compiler. But,
please, can you elaborate how it masks the error and how stdlib.h helps
in conversion of type void * to target pointer type? i mean, how it
determines the target pointer type, if i am using a C compiler.
 
R

Richard Heathfield

chandan said:
In my case, i was trying to compile this code with a C++ compiler.

That's always a mistake. You wouldn't try to compile Algol with a Pascal
compiler, so why compile C with a C++ compiler?
But,
please, can you elaborate how it masks the error and how stdlib.h helps

It provides a full prototype for calloc, thus telling the compiler that
malloc returns void *.
in conversion of type void * to target pointer type?

By telling the compiler that calloc returns void *, the prototype assists in
the generation of correct code. Without the prototype, the compiler would
be forced to assume that calloc returns int (which calloc doesn't in fact
return).

In the following example, I use malloc rather than calloc, for the simple
reason that experienced C programmers hardly ever use calloc as its side
effect is generally (but not quite always) unnecessary, but the reasoning
is identical.
i mean, how it
determines the target pointer type, if i am using a C compiler.

#include <stdio.h> /* for printf prototype */
#include <stdlib.h> /* for malloc prototype */

typedef int T; /* any object type will do here */

int main(void)
{
T *p; /* compiler now knows p has type T *, so all is well */
size_t n = 42; /* compiler now knows n has type size_t, so all is well */
p = malloc(n * sizeof *p); /* malloc returns void *, and the compiler
* knows that p has type T *, and the
* compiler knows how to convert
* between void * and T *, so there is
* no problem here. */
if(p != NULL)
{
printf("Yes, I got the memory. It's at %p.\n", (void *)p);
free(p);
}

return 0;
}
 
M

Martin Ambuhl

chandan said:
i am sorry for the silly abbreviations, i had used. Thanks, for the
advice.




I never told that i know everything.

*Everything* you wrote was wrong. It is not a question of your knowing
everything: everything you "know" is wrong and you have no business
inflicting your ignorance on others as advice.
 
C

chandan

Richard said:
/* malloc returns void *, and the compiler
* knows that p has type T *, and the
* compiler knows how to convert
* between void * and T *, so there is
* no problem here. */

Richard, i got your point. But, still I have a little confusion.

In section 7.8.5 of K&R, they mention that

The pointer returned by malloc or calloc has the proper alignment for
the object in question, but it must be cast into the appropriate type,
as in
int *ip;
ip = (int *) calloc(n, sizeof(int));

Is the above given statement is no longer valid? And, if it is valid
statement, then which point i am missing, now?
 
R

Richard Heathfield

chandan said:
Richard, i got your point. But, still I have a little confusion.

In section 7.8.5 of K&R, they mention that

The pointer returned by malloc or calloc has the proper alignment for
the object in question, but it must be cast into the appropriate type,

Yes, K&R got it wrong. The cast is not required. The following quote is from
Dennis Ritchie's "errata" site:

"142(§6.5, toward the end): The remark about casting the return value of
malloc ("the proper method is to declare ... then explicitly coerce") needs
to be rewritten. The example is correct and works, but the advice is
debatable in the context of the 1988-1989 ANSI/ISO standards. It's not
necessary (given that coercion of void * to ALMOSTANYTYPE * is automatic),
and possibly harmful if malloc, or a proxy for it, fails to be declared as
returning void *. The explicit cast can cover up an unintended error. On
the other hand, pre-ANSI, the cast was necessary, and it is in C++ also."

Taken from: <http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html>
 
C

chandan

Martin said:
*Everything* you wrote was wrong. It is not a question of your knowing
everything: everything you "know" is wrong and you have no business
inflicting your ignorance on others as advice.

Cool down, man!! Why, you are showing so much aggression?
everything: everything you "know" is wrong.

No, not now.... :). Feeling happy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top