user2607801
user2607801

Reputation:

why first code give error and second does not?

This is the first code:

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

void test(int,int);

int main()
{
  int p=23,f=24;
  test(&p,&f); 
  printf("%d %d\n",p,f);
  return 0;  
}

void test(int q,int g)
{
  q=q+q;  
  g=g+g;
}

This code generates TYPE MISMATCH ERROR maybe due to the fact that I have passed address of variable as argument during function calling and the formal parameters are not pointers.

This is the second code:

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

int main()
{    
  int p=23,f=24,q,g;
  q=&p;
  g=&f;
  printf("%d %d\n",q,g);
  return 0;
}

The output of second code is

1638220 1638228

In this code, q and g are not pointers. So why are they giving correct output, not the error?

Upvotes: 1

Views: 129

Answers (1)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76397

Note:
Your comment: "The second code prints the correct addresses of p and f where as first code gives error" is wrong on various levels.
You claim your printf statement prints the memory addresses of the variables? Wrong, it does no such thing. Can't. Impossible. Not going to happen.
To print the memory addresses of variables, a printf statement should look like this:

printf("p @ %p\nf @ %p\n", (void *) &p, (void *) &f);//one of few cases where you SHOULD cast

You're printing just a number:

printf("%d %d", p, f);

Those are not the same thing. Just take a look at the example at the bottom of this answer, but read the bit in the middle, too

Well, you declared q and g as ints, and assigned them the memory addresses of p and f. It's undefined behaviour (ie the standard doesn't determine what to do with this, so it may vary depending on the compiler, WCS: your application crashes). In your case, I'd say this happens:
Basically, a memory address looks something like this:

0x213ABC

A hexadecimal value, which can be interpreted as a number, so there's nothing stopping your from assigning it to a char, or size_t or whatever.
HOWEVER, if you compile your code with -Wall, you should get a warning about the implicit conversion from type int * to int. Aside from that, you're "safe". Mind your: the program's output will be unpredictable and therefore rather pointless.

The first snippet contains a bigger problem: you're passing a value to a function that simply does not exist! The test function cannot handle what you're passing, because its prototype shows it expects 2 ints, not 2 pointers

test(&p,&f);
//to:
test((int) &p,(int) &f);

However, it does compile, as you can see here, however the results are unpredictable (undefined behaviour).

When calling test(&p, &f) you are calling a function that should look like this:

void test(int *, int *)

However, this signature/prototype is nowhere to be found, so the compiler can't continue. Casting the memory addresses to ints changes all that, and lets the compiler know that the function looks like void test (int, int), and that function does exist, hence it compiles.

Think of it like this:

You: What's your phone-number?
Me: abc
you: That's not a phone number
Me: I meant 1-11-111 (number keys for text messages, those were the days)

That's what you're doing here:

test(&p, &f);
//compiler: can't find function test(int *, int *)
//you: I expect you to call test(int, int), and implicitly cast the pointers to ints

That's not how C works.

Note:
As pointed out to me in the coments: Assigning/casting pointer to int is undefined behaviour (ie: the result of these actions are not defined by the standard)


The example program that prints pointers, and unsigned long and ints as they should be printed:

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

int main( void )
{
    int p = 2, f = 4, q;
    q = (int) &f;
    printf("p @ %p\nf @ %p\n", (void *) &p, (void *) &f);
    //int is too small for 64bit address, use unsigned long here
    printf("%d != %ul != %p\n", q, &f, (void *) &f);
    return EXIT_SUCCESS;
}

When I ran it through this codepad, I got the following output:

p @ 0xbf70e1d8
f @ 0xbf70e1d4
-1083121196 != 3211846100l != 0xbf70e1d4

Upvotes: 3

Related Questions