tags:

views:

86

answers:

6

I have the following code. but i m getting incorrect output can anybody define me that why output is 10 B only & why m not getting A in output.. ?? plz help me out......

#include<stdio.h>
#include<conio.h>
void main()
{
    int *p;
    char c,d;
    int i;

    clrscr();
    p=&i;
    *p=10;
    (char *)p=&c;
    *p=65;
    (char *)p=&d;
    *p=66;
    printf("%d%c%c",i,c,d);
    getch();
}
+3  A: 

Your program invokes undefined behavior, so there's no correct or incorrect. Specifically:

*p = 65;

writes an integer into memory with only room for a char. C99 §6.5.3.2/4 (Address and indirection operations) states:

If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.84)

p has type pointer to int, so *p has type int. However, p is not a the address of a valid int object.

Also, I believe the cast on the left side of the assignment is illegal (GCC definitely thinks so).

I believe what's happening is that it's laid out (increasing addressess) like:

|i|i|i|i|d|c|p|p|p|p|

This represents the bytes each occupies. I'll walk through what I think is happening:

p = &i;

|i|i|i|i|d|c|00|00|00|00|

For simplicity, I assume the address of i is 0.

*p=10;

|10|0|0|0|d|c|00|00|00|00|

p=&c;

|10|0|0|0|d|c|05|00|00|00|

*p=65;

|i|i|i|i|d|65|00|00|00|00|

Note that modifying *p overwrites p.

p=&d;

|10|0|0|0|d|65|04|00|00|00|

*p=66;

|10|0|0|0|66|00|00|00|00|00|

So storing to d overwrites c with NULL. The above applies if your machine is little-endian, has 4-byte ints, and the stack grows upwards (towards lower addresses). The analysis is different if you have 2-byte ints, but the main conclusion still applies.

Returning void is also illegal, but that's unrelated.

Matthew Flaschen
@Matthew: I don't think that the assignment of the `int`'s here can be the problem. They are all in the guaranteed range of `char`, no? As long as the value of such an assignment fits there is no undefined behavior. BTW, things as `'a'` or `'\n'` are `int`, too.
Jens Gustedt
@Jens, no, the range doesn't matter. Storing an int (i.e. having an int on the left side of `=`) is still going to write `sizeof(int)` bytes. I am aware that character constants like `'a'` are ints.
Matthew Flaschen
@Matthew, ah, sorry I probably misread, then.
Jens Gustedt
A: 

I could not compile your program, it does not conform to ANSI standard. Here is fixed version and it prints "10AB":

#include<stdio.h>

int main()
{

int *p;
char *cp;
char c,d;
int i;
p=&i;
*p=10;
cp=&c;
*cp=65;
cp=&d;
*cp=66;
printf("%d%c%c\n",i,c,d);
}
Lavir the Whiolet
A: 

You are using the casting operator in wrong way. You an assiging an char * to int *. So you should cast that char * to allow the conversion. The correct code is as below:

int *p; char c,d; int i; 
p=&i; 
*p=10; 
p=(int *)&c; 
*p=65; 
p=(int *)&d; 
*p=66; 
printf("%d%c%c",i,c,d); 
This code still invokes undefined behavior by storing an `int` where only a `char` will fit.
Matthew Flaschen
+3  A: 

The statement (char *)p=&c; doesn't magically turn p into a char * from that point on. In the next line, *p=65;, you're still putting an int into that location.

Ditto for (char *)p=&d; *p=66;. Now because you're inserting what's almost certainly two bytes into the single byte d, you're probably overwriting c with 0.

You may find that changing *p = 66 to *((char*)p) = 66 will give you what you want, the insertion of a single byte.

And, please, upgrade to gcc if possible. It costs exactly the same as Turbo C and is better in just about every way.

paxdiablo
+1  A: 

You want to use

p = (int *) &c;

but when you do

*p = 65

then the compiled program will put 65, as a 4-byte value (assuming your int is 4 byte) into the memory where c is residing. It will trash 3 more bytes... because c is only 1 byte, and you are putting 4 bytes of data into it... and I wonder whether some platform will complain as c is a char, and may not be at an int boundary...

You probably want to use

char *pChar = &c;
*pChar = 65;

If you want to experiment with putting a byte 65 into the integer i, you can use

pChar = (char *) &i;
*pChar = 65;

The (char *) is called casting -- making it a pointer to character.

動靜能量
A: 

Your main problem is that the whole thing is a hack. Don't do that. There is no reason to cast int or char back and forth like that. You can only expect trouble from the way you write your code.

Some hints:

  • the correct include file for standard C is stdio.h
  • in C the expression (char*)p is not an lvalue, meaning that you can't assign to it. (this has good reasons)
  • Even if you would succeed to assign the address of a char to an int pointer this would generally a bad idea. Not only because you will eventually override memory that is not "yours" but also because of alignment problems. The best that can happen to you in such a case is a bus error, to tell you early that you are on the wrong track
  • the return type of main is int
Jens Gustedt