-1

Why the below code is not printing the value 10? rather it crashes..

void foobar(int *a) 
{   
    int *c;
    c = *a;

    printf("%d\n", *c);
}

int main(void)
{   
    int *b = (int *)malloc(sizeof(int));
    *b = 10;
    foobar(&b);
}   
Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • 2
    [Don't cast the return value of `malloc()`.](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858) Compile with warnings enabled and **pay attention to warnings.** In particular, look for "incompatible types in assignment" or similar. Also, **think about** what the code does (what the meaning of each of the declarations and the `&` operator is, etc.) –  Nov 25 '13 at 18:05
  • 1
    what you want to archive by `c = *a;`? – Andriy Tylychko Nov 25 '13 at 18:06
  • 1
    Crash probably caused by pointers being larger than an `int`, see igoris answer below. – epatel Nov 25 '13 at 18:17

6 Answers6

2

Try making these small changes.

#include <stdio.h>
#include <malloc.h>

void foobar(int *a) {
  printf("%d\n", *a); /* what was C about? */
}

int main(void) {
  int *b = malloc(sizeof(int));
  *b = 10;
  foobar(b); /* pass the pointer b, not the address of the pointer b. */
  free(b);
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

At first you should include stdio.h and stdlib.h

Second, your function declaration is incorrect. It should be

void foobar(int **a)

instead of

void foobar(int *a)  

Because you are passing pointer to pointer.

igoris
  • 1,476
  • 10
  • 20
0

The code misses to include <stdlib.h> and most likley runs on 64 bit.

To fix it do:

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

void foobar(int ** a)  /* Fixed wrong type. */
{   
  int * c = *a;

  printf("%d\n", *c);
}

int main(void)
{    
  int * b = malloc(sizeof(*b)); /* Removed unnecessary and dangerous cast. */
  if (NULL != b) /* Added error checking. */
  {
    *b = 10;

    foobar(&b);
  }

  free(b); /* Added clean up. */

  return 0; /* Added return (unnecessary from C99 on). */
}  
alk
  • 69,737
  • 10
  • 105
  • 255
0
#include <stdio.h>
#include<stdlib.h> //--------> ERROR 3: INCLUDE STDLIB FOR MALLOC() FUNCTION

 void foobar(int *a)
{
    int *c;
    c = *a; //--------->ERROR 2 : C POINTS TO THE CONTENTS OF A POINTER

    printf("%d\n", *c);
}

 // SOLUTION 1 : KEEP FUNCTION PROTOTYPE SAME AND PASS B TO FOOBAR AND MAKE C POINT TO    A.
 // SOLUTION 2 : CHANGE FOOBAR'S PROTOTYPE TO FOOBAR(INT**A).

 int main(void)
{
     int *b = (int *)malloc(sizeof(int));
     *b = 10;
     foobar(b); //-------->ERROR 1 : PASSING THE ADDRESS OD A POINTER VARIABLE

}

solution 1 :foobar(b); in main and c=a;

solution 2 :foobar(int **a);

Rafed Nole
  • 112
  • 1
  • 4
  • 16
0

Crashed due to wrong argument type in void foobar(int *a)

It should have been void foobar(int **a)

Though for requirement just correct foobar(&b) => foobar(b)

dev
  • 137
  • 1
  • 1
  • 5
0

Let's talk about types for a minute.

Given the declaration

T *p;

then the following are all true:

Expression         Type        Value
----------         ----        -----
         p         T *         Address of the thing p points to
        *p         T           Value of the thing p points to
        &p         T **        Address of the variable p

In main, you declare b as int *. In foobar, you declare both a and c as type int *.

In the call to foobar, you're using the expression &b, which has type int **; this doesn't match up with the type of a (and should have resulted in a diagnostic from the compiler). What you're doing is passing the address of the variable b to foobar, which is not what you want; you want to pass the value contained in b, which is the address of the memory you grabbed from the malloc call. So if you change your call to foobar to read

foobar(b);

the code should work as you expect.

A picture might help a bit. All of the addresses are pulled out of thin air, and are not meant to represent any real-world platform; assume big-endian representation as well:

Item        Address        0x00  0x01  0x02  0x03
----        -------        ----  ----  ----  ----
heap memory 0x00800000     0x00  0x00  0x00  0x0a
   b        0xfff78000     0x00  0x80  0x00  0x00
   a        0xfff781c0     0x00  0x80  0x00  0x00
   c        0xfff781c4     0x00  0x80  0x00  0x00

The call to malloc allocates 4 bytes starting at address 0x008000000; after the assignment *b = 10, those four bytes contain the value 0x0000000a.

b, a, and c are all variables with auto extent; all three contain the heap memory address as their value. The expressions *b, *a, and *c should all evaluate to whatever's being stored at address 0x008000000; that is, the integer value 10. &b evaluates to the address of b, or 0xfff78000.

As others have mentioned, don't cast the result of malloc. It's not required (at least, not in C as of the 1989 standard; C++ and earlier versions of C are different stories), and under the 1989 standard it can suppress a useful diagnostic if you forgot to #include stdio.h or otherwise don't have a declaration for malloc in scope. The general form for a malloc call is

T *p = malloc( sizeof *p * num_elements );

so in your case it would read

int *b = malloc( sizeof *b );

Note that you should always clean up after yourself, even for toy programs like this, so you'll want to add

free( b );

before you exit your program.

John Bode
  • 119,563
  • 19
  • 122
  • 198