Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Newbie needs help with pointers/memory allocation

Reply
Thread Tools

Newbie needs help with pointers/memory allocation

 
 
Me Alone
Guest
Posts: n/a
 
      08-16-2006
Hello list:

I am working on a C assignment. I am to declare a (pointer to pointer
to int), allocate memory for pointer and data, and print some output.

Problem (I think): The memory addresses printed don't look right. Would
any one be so kind to take a look at my code and explain why are the
addresses for the lists printed in "less than optimal" sequence?

Thanks in advance,
Ron

##########################################

#include <stdio.h>

#define T1 2
#define T2 5

main()
{
int i, j, **ptr;

if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)
{
error("Error encountered, will exit now.");
exit(0);
}

if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)
{
error("Error encountered, will exit now.");
exit(0);
}

for(i=0;i<T1;i++)
{
printf("\nData in table (%d).\n", i);
printf("**ptr addr\t*ptr addr\tvalue\n");
printf("=====================================\n");
for(j=0;j<T2;j++)
{
if(i > 0)
{
*(ptr+i+j) = j + T2;
printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));
} else {
*(ptr+i+j) = j;
printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
}
}
}
printf("\n");
}


// Output of program
Data in table (0).
**ptr addr *ptr addr value
=====================================
BFF06C84 BFF06C84 0
BFF06C84 BFF06C88 1
BFF06C84 BFF06C8C 2
BFF06C84 BFF06C90 3
BFF06C84 BFF06C94 4

Data in table (1).
**ptr addr *ptr addr value
=====================================
BFF06C88 BFF06C88 5
BFF06C88 BFF06C8C 6
BFF06C88 BFF06C90 7
BFF06C88 BFF06C94 8
BFF06C88 BFF06C98 9

 
Reply With Quote
 
 
 
 
Frederick Gotham
Guest
Posts: n/a
 
      08-16-2006
Me Alone posted:

> Hello list:
>
> I am working on a C assignment. I am to declare a (pointer to pointer
> to int), allocate memory for pointer and data, and print some output.



The following might get you going:

#include <stdio.h>

#define AL(arr) (sizeof(arr)/sizeof*(arr))

int main(void)
{
int const iarr[] = {0,1,2,3,4,5,6,7,8,9};

int const *const parr[] = {iarr,iarr+1,iarr+2,iarr+3,iarr+4,
iarr+5,iarr+6,iarr+7,iarr+8,iarr+9};

int const *const *p = parr;

int const *const *const p_over = parr + AL(parr);

do
{
printf("%d",**p++);
} while(p != p_over);

return 0;
}


> #include <stdio.h>



You'l also want:

#include <stdlib.h>


> #define T1 2
> #define T2 5
>
> main()



Change that to:

int main(void)


> {
> int i, j, **ptr;
>
> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)



Don't cast the return value of "malloc" -- it makes you look like a novice.

Try this:

if( !(ptr = malloc(T1 * sizeof*ptr)) )


> {
> error("Error encountered, will exit now.");
> exit(0);
> }
>
> if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)



Again, don't cast the return value of malloc.

if( !(*ptr = malloc(T1 * T2 * sizeof**ptr)) )

Sorry, I'd examine the rest of your code, but my brain's taken enough
screen-staring for today.

--

Frederick Gotham
 
Reply With Quote
 
 
 
 
Barry Schwarz
Guest
Posts: n/a
 
      08-17-2006
On Wed, 16 Aug 2006 18:06:53 -0500, Me Alone <(E-Mail Removed)> wrote:

>Hello list:
>
>I am working on a C assignment. I am to declare a (pointer to pointer
>to int), allocate memory for pointer and data, and print some output.
>
>Problem (I think): The memory addresses printed don't look right. Would
>any one be so kind to take a look at my code and explain why are the
>addresses for the lists printed in "less than optimal" sequence?
>
>Thanks in advance,
>Ron
>
>##########################################
>
>#include <stdio.h>


You need stdlib.h for malloc.

>
>#define T1 2
>#define T2 5
>
>main()
>{
> int i, j, **ptr;
>
> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)


Don't cast the return from malloc. It never helps but can cause the
compiler to suppress a diagnostic you would really like to see. And
your code does have the error which the compiler would catch.

ptr points to an uninitialized array of 2 int*.

> {
> error("Error encountered, will exit now.");


There is no error function defined.

> exit(0);
> }
>
> if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)


*ptr (which is the same as ptr[0]) points to an array of 10 int.

> {
> error("Error encountered, will exit now.");
> exit(0);
> }
>
> for(i=0;i<T1;i++)
> {
> printf("\nData in table (%d).\n", i);
> printf("**ptr addr\t*ptr addr\tvalue\n");
> printf("=====================================\n");
> for(j=0;j<T2;j++)
> {
> if(i > 0)
> {
> *(ptr+i+j) = j + T2;
> printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));


& has higher precedence than +. This evaluates as (&ptr)+i. Since
ptr has type int**, &ptr has type int***. So does the sum. I'm
pretty sure this is not what you wanted. When i+j > 1, the expression
&ptr+i+j is not a valid value.

If you want to print addresses using printf, you should use %p and
cast the value to void*.

> } else {
> *(ptr+i+j) = j;


*(ptr+i+j) is the same as ptr[i+j]. Since ptr is an int**, ptr[i+j]
is an int*. j is an int. You cannot assign an int to an int* without
a cast (and in this program you don't even want to). Did your
compiler not generate a diagnostic here? If not, you need to up the
warning level so it does.

> printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
> }
> }
> }
> printf("\n");
>}
>
>
>// Output of program


Why did you execute a program that does not compile cleanly?

>Data in table (0).
>**ptr addr *ptr addr value
>=====================================
>BFF06C84 BFF06C84 0
>BFF06C84 BFF06C88 1
>BFF06C84 BFF06C8C 2
>BFF06C84 BFF06C90 3
>BFF06C84 BFF06C94 4
>
>Data in table (1).
>**ptr addr *ptr addr value
>=====================================
>BFF06C88 BFF06C88 5
>BFF06C88 BFF06C8C 6
>BFF06C88 BFF06C90 7
>BFF06C88 BFF06C94 8
>BFF06C88 BFF06C98 9



Remove del for email
 
Reply With Quote
 
Andrew Poelstra
Guest
Posts: n/a
 
      08-17-2006
On 2006-08-16, Me Alone <(E-Mail Removed)> wrote:
> Hello list:
>
> I am working on a C assignment. I am to declare a (pointer to pointer
> to int), allocate memory for pointer and data, and print some output.
>
> Problem (I think): The memory addresses printed don't look right. Would
> any one be so kind to take a look at my code and explain why are the
> addresses for the lists printed in "less than optimal" sequence?
>
> Thanks in advance,
> Ron
>
> ##########################################
>
> #include <stdio.h>
>
> #define T1 2
> #define T2 5
>


Magic numbers are almost better than these unmeaningful macros. You
should have better names.

> main()


int main (void) is the preferred style, and one that will work with C99.

> {
> int i, j, **ptr;


Don't declare pointers and non-pointers on the same line; they're
different types. This is legal, but poor style.

>
> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)


1) There's no reason to have an assignment in an if statement; move it
to the line above for more readability. (This isn't too important for
such a short line.)
2) Don't cast the result of malloc(). It hides the fact that you didn't
include <stdlib.h> and causes undefined behavior.
3) Don't use sizeof on a type. It's almost never what you want to do.

ptr = malloc (T1 * sizeof *ptr);
if (ptr == NULL)
...

> {
> error("Error encountered, will exit now.");


1) error() is not a standard function. We at clc have no idea what it does.
2) This error message is thoroughly useless; describe the problem.

> exit(0);


exit (EXIT_FAILURE); would be better.

> }
>
> if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)
> {
> error("Error encountered, will exit now.");
> exit(0);
> }
>


Ditto.

> for(i=0;i<T1;i++)
> {
> printf("\nData in table (%d).\n", i);
> printf("**ptr addr\t*ptr addr\tvalue\n");
> printf("=====================================\n");
> for(j=0;j<T2;j++)
> {
> if(i > 0)
> {
> *(ptr+i+j) = j + T2;
> printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));
> } else {
> *(ptr+i+j) = j;
> printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
> }
> }
> }
> printf("\n");
> }
>


To print the value of a pointer, use %p and cast to void*:
printf ("Value of my pointer: %p\n", (void *) ptr);

>
> // Output of program

[Demons extracted from nose and are forced to ride a purple donkey.]
[Or maybe not. Anything can happen with Undefined Behavior.]

--
Andrew Poelstra <http://www.wpsoftware.net/projects>
To reach me by email, use `apoelstra' at the above domain.
"Do BOTH ends of the cable need to be plugged in?" -Anon.
 
Reply With Quote
 
Herbert Rosenau
Guest
Posts: n/a
 
      08-17-2006
On Wed, 16 Aug 2006 23:06:53 UTC, Me Alone <(E-Mail Removed)> wrote:

> Hello list:
>
> I am working on a C assignment. I am to declare a (pointer to pointer
> to int), allocate memory for pointer and data, and print some output.
>
> Problem (I think): The memory addresses printed don't look right. Would
> any one be so kind to take a look at my code and explain why are the
> addresses for the lists printed in "less than optimal" sequence?
>
> Thanks in advance,
> Ron
>
> ##########################################
>
> #include <stdio.h>
>
> #define T1 2
> #define T2 5
>
> main()


Has to be
int main(void)
since more than 16 years now.

> {
> int i, j, **ptr;
>
> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)


Casting the result of malloc ends up in undefined behaviuor in special
when one forgets to include stdlib.h. And even when you includes
stdlib.h it is a faiture to cast.

In C there is already never a need to cast a pointer to void. Only a
dumbass who knows not what he does is able to cast a pointer to void
to anything else or cast a pointer to any datatype to a pointer to
void.

A programmer who knows what he is doing will avoid any cast only
because the compiler gives a diagnostic as he knows that the
diagnostic shows an error he'd made and the error is NOT becaue he'd
forgotten to cast.

> {
> error("Error encountered, will exit now.");
> exit(0);
> }
>
> if ((*ptr = (int*)malloc(T1 * T2 * sizeof(int))) == NULL)


The same as above.

> {
> error("Error encountered, will exit now.");
> exit(0);
> }
>
> for(i=0;i<T1;i++)
> {
> printf("\nData in table (%d).\n", i);
> printf("**ptr addr\t*ptr addr\tvalue\n");
> printf("=====================================\n");
> for(j=0;j<T2;j++)
> {
> if(i > 0)
> {
> *(ptr+i+j) = j + T2;
> printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, (ptr+i+j));
> } else {
> *(ptr+i+j) = j;
> printf("%X\t%X\t%d\n", &ptr+i, &ptr+i+j, *(ptr+i+j));
> }
> }
> }
> printf("\n");
> }
>
>
> // Output of program
> Data in table (0).
> **ptr addr *ptr addr value
> =====================================
> BFF06C84 BFF06C84 0
> BFF06C84 BFF06C88 1
> BFF06C84 BFF06C8C 2
> BFF06C84 BFF06C90 3
> BFF06C84 BFF06C94 4
>
> Data in table (1).
> **ptr addr *ptr addr value
> =====================================
> BFF06C88 BFF06C88 5
> BFF06C88 BFF06C8C 6
> BFF06C88 BFF06C90 7
> BFF06C88 BFF06C94 8
> BFF06C88 BFF06C98 9
>


Repair your program by removing the casts and the real cause the
compiler complains.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
 
Reply With Quote
 
Harald van =?UTF-8?B?RMSzaw==?=
Guest
Posts: n/a
 
      08-17-2006
Herbert Rosenau wrote:
> On Wed, 16 Aug 2006 23:06:53 UTC, Me Alone <(E-Mail Removed)> wrote:
>
>> Hello list:
>>
>> I am working on a C assignment. I am to declare a (pointer to pointer
>> to int), allocate memory for pointer and data, and print some output.
>>
>> Problem (I think): The memory addresses printed don't look right. Would
>> any one be so kind to take a look at my code and explain why are the
>> addresses for the lists printed in "less than optimal" sequence?
>>
>> Thanks in advance,
>> Ron
>>
>> ##########################################
>>
>> #include <stdio.h>
>>
>> #define T1 2
>> #define T2 5
>>
>> main()

>
> Has to be
> int main(void)
> since more than 16 years now.


In C89, main() is valid. It declares main() as returning int and taking no
parameters. The lack of a prototype only affects how and when diagnostics
are generated for invalid recursive calls to main(), and the lack of an
explicit return type is at worst bad style.

>> {
>> int i, j, **ptr;
>>
>> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)

>
> Casting the result of malloc ends up in undefined behaviuor in special
> when one forgets to include stdlib.h.


Thanks for at least clarifying this now, but there's still one minor thing.
The behaviour is well-defined if malloc() is called with a proper
declaration in scope. This can happen with or without including <stdlib.h>:

#include <stddef.h>

extern void *malloc(size_t);
extern void free(void *);

int main(void) {
free(malloc(1)); /* no undefined behaviour */
free((char *) malloc(1)); /* still no undefined behaviour */
return 0;
}

> And even when you includes
> stdlib.h it is a faiture to cast.


Rather, it's considered bad style in most cases.

> In C there is already never a need to cast a pointer to void. Only a
> dumbass who knows not what he does is able to cast a pointer to void
> to anything else or cast a pointer to any datatype to a pointer to
> void.


You never answered how you would store a pointer value in an object of type
intptr_t or uintptr_t. Or do only dumbasses do that? Do real programmers
use intptr_t to store currency values, perhaps?

> A programmer who knows what he is doing will avoid any cast only
> because the compiler gives a diagnostic as he knows that the
> diagnostic shows an error he'd made and the error is NOT becaue he'd
> forgotten to cast.


Here you go again with your overly broad claims. "Any" cast? Do you want to
clarify that?
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-17-2006
"Herbert Rosenau" <(E-Mail Removed)> writes:
> On Wed, 16 Aug 2006 23:06:53 UTC, Me Alone <(E-Mail Removed)> wrote:
>> I am working on a C assignment. I am to declare a (pointer to pointer
>> to int), allocate memory for pointer and data, and print some output.
>>
>> Problem (I think): The memory addresses printed don't look right. Would
>> any one be so kind to take a look at my code and explain why are the
>> addresses for the lists printed in "less than optimal" sequence?
>>
>> Thanks in advance,
>> Ron
>>
>> ##########################################
>>
>> #include <stdio.h>
>>
>> #define T1 2
>> #define T2 5
>>
>> main()

>
> Has to be
> int main(void)
> since more than 16 years now.


That's incorrect. In C90, "main()" is perfectly legal, and if I
recall correctly you'll find multiple instances of it in examples in
K&R2. C99 removed implicit int from the language, making "main()" a
constraint violation, but few compilers enforce this unless they're
specifically invoked in a strict C99-conforming mode.

"int main(void)" is better than "main()", and it has been since the
ANSI standard was introduced in 1989, but there's no need to overstate
the case.

>> {
>> int i, j, **ptr;
>>
>> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)

>
> Casting the result of malloc ends up in undefined behaviuor in special
> when one forgets to include stdlib.h. And even when you includes
> stdlib.h it is a faiture to cast.


Didn't we just go over this?

No, casting the result of malloc() does not invoke undefined behavior.
If there's no visible prototype for malloc() (the way to get one is
"#include <stdlib.h>"), then just *calling* malloc() invokes undefined
behavior, regardless of what you do with the result.

See the FAQ for more information.

> In C there is already never a need to cast a pointer to void. Only a
> dumbass who knows not what he does is able to cast a pointer to void
> to anything else or cast a pointer to any datatype to a pointer to
> void.


I haven't found that calling people "dumbasses" is a particularly
effective teaching tool. Does it work for you?

You're absolutely correct that casting the result of malloc() is not
necessary and should be avoided. Please don't give misleading advice
about *why* it's a bad idea.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-17-2006
Harald van Dijk <(E-Mail Removed)> writes:
> Herbert Rosenau wrote:

[...]
>> A programmer who knows what he is doing will avoid any cast only
>> because the compiler gives a diagnostic as he knows that the
>> diagnostic shows an error he'd made and the error is NOT becaue he'd
>> forgotten to cast.

>
> Here you go again with your overly broad claims. "Any" cast? Do you want to
> clarify that?


I think what he meant here is that any cast that's added merely for
the purpose of shutting up a compiler diagnostic is a bad idea.

There are cases where casts are appropriate. There are far fewer such
cases than many C programmers seem to believe.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Harald van =?UTF-8?B?RMSzaw==?=
Guest
Posts: n/a
 
      08-18-2006
Keith Thompson wrote:

> Harald van Dijk <(E-Mail Removed)> writes:
>> Herbert Rosenau wrote:

> [...]
>>> A programmer who knows what he is doing will avoid any cast only
>>> because the compiler gives a diagnostic as he knows that the
>>> diagnostic shows an error he'd made and the error is NOT becaue he'd
>>> forgotten to cast.

>>
>> Here you go again with your overly broad claims. "Any" cast? Do you want
>> to clarify that?

>
> I think what he meant here is that any cast that's added merely for
> the purpose of shutting up a compiler diagnostic is a bad idea.


Which is why I asked for clarification. My compiler generates a diagnostic
for

long long i = 1 << 40;

Adding a cast to shut it up:

long long i = (long long) 1 << 40;

is one way of fixing the code. (A suffix is another, but that is not an
option when using a variable.)

> There are cases where casts are appropriate. There are far fewer such
> cases than many C programmers seem to believe.


Probably so.
 
Reply With Quote
 
Herbert Rosenau
Guest
Posts: n/a
 
      08-18-2006
On Thu, 17 Aug 2006 22:42:36 UTC, Keith Thompson <(E-Mail Removed)>
wrote:

> >>
> >> main()

> >
> > Has to be
> > int main(void)
> > since more than 16 years now.

>
> That's incorrect. In C90, "main()" is perfectly legal, and if I
> recall correctly you'll find multiple instances of it in examples in
> K&R2. C99 removed implicit int from the language, making "main()" a
> constraint violation, but few compilers enforce this unless they're
> specifically invoked in a strict C99-conforming mode.


It is deprecated anyway. Using that will hinder you to to to ANSI99
always. 16 years of standard should be enough to accept that.

> "int main(void)" is better than "main()", and it has been since the
> ANSI standard was introduced in 1989, but there's no need to overstate
> the case.
>
> >> {
> >> int i, j, **ptr;
> >>
> >> if ((ptr = (int**)malloc(T1 * sizeof(int*))) == NULL)

> >
> > Casting the result of malloc ends up in undefined behaviuor in special
> > when one forgets to include stdlib.h. And even when you includes
> > stdlib.h it is a faiture to cast.

>
> Didn't we just go over this?
>
> No, casting the result of malloc() does not invoke undefined behavior.
> If there's no visible prototype for malloc() (the way to get one is
> "#include <stdlib.h>"), then just *calling* malloc() invokes undefined
> behavior, regardless of what you do with the result.


I've seen idiots removing #include <stdlib.h> and then failing into
undefined behavior on malloc().

Have you never learned to program failsave?

> See the FAQ for more information.
>
> > In C there is already never a need to cast a pointer to void. Only a
> > dumbass who knows not what he does is able to cast a pointer to void
> > to anything else or cast a pointer to any datatype to a pointer to
> > void.

>
> I haven't found that calling people "dumbasses" is a particularly
> effective teaching tool. Does it work for you?
>
> You're absolutely correct that casting the result of malloc() is not
> necessary and should be avoided. Please don't give misleading advice
> about *why* it's a bad idea.
>

It IS a bad idea because
- undiefined behavior occures when stdlib is not included.
Having it yet included does not mean that somebody will remove
that sometimes later. Not anybody knows that already as
this group shows nearly dayly.
- undefined behavior is guaranteed because the standard dos not
tell that
- int is always the same size as void*
- the environemt uses even the same location to return int
and pointer values as the standard does allows that.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
An idea for heap allocation at near stack allocation speed Bjarke Hammersholt Roune C++ 14 03-06-2011 08:07 AM
static memory allocation versus dynamic memory allocation Ken C Programming 24 11-30-2006 12:37 AM
What is the difference between dynamic memory allocation,and stack allocation ? chris C++ 6 10-28-2005 05:27 AM
Thunderbird Newbie Needs Help D a v e Firefox 11 01-25-2005 06:45 PM
Newbie needs help on implementing directory walk SD Perl 1 10-10-2003 11:46 AM



Advertisments