Code problem

R

rage

Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;
i=j+19;
printf("%d %d\n",j,i);
}

The output is a garbage value (86) on my pc and ideone. Should it not be 29?
 
E

Eric Sosman

Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;

What are you trying to accomplish with this line? Your compiler
should have given you a diagnostic message about it; what did the
message say, and what meaning did you think it had?

Should have received another diagnostic message for this line.
printf("%d %d\n",j,i);

No diagnostic is *required* for this line, but some compilers
are smart and helpful enough to issue one.
}

The output is a garbage value (86) on my pc and ideone. Should it not be 29?

Your code's behavior is undefined, so there is no reason you
"should" expect any particular output, nor even any output at all.
What are you trying to do?
 
K

Kaz Kylheku

Can someone please help me out on this?

Your code is not a well-formed ISO C program. It contains type system
violations that require a diagnostic.
#include<stdio.h>
main()
{
int i;
int *j=10;

Here, a variable of pointer type is being initialized with an integer value.

Here, an integer object is being assigned from a pointer expression.
printf("%d %d\n",j,i);

Here, the %d conversion specifier, which requires a matching argument of type
int, is given an argument of type "int *". This is undefined behavior.
}

The output is a garbage value (86) on my pc and ideone. Should it not be 29?

Since the program requires diagnostics, the ISO C standard doesn't require the
implementation to translate and execute the program. If the program translates
and executes anyway, its behavior is not defined by ISO C. Of course, it has a
behavior, but implementation-specific reasoning is required to understand it.

For instance, whether or not you can print a pointer using %d will depend
on the calling conventions, and that can be sensitive to different versions
of even the same compiler. What if pointers are 64 bits wide but int is 32
bits? In that case it is conceivable that "%d %d" will just take two halves
of the 64 bit j value, and i is ignored.

This kind of program is usually not correct even according to the local
compiler and library documentation, never mind ISO C.
 
A

Angel

Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;

In this line, you're converting an integer value to a pointer. That
is an operation with undefined behavior. (Except if the integer is a
constant value of zero, if I recall right.)

Because of this undefined behavior, your program may not compile at
all. Even if it does, it may not run. Even if it runs, it may not give
any sensible output. Undefined behavior basically means "sorry mate,
you're on your own here".

Do you actually know what pointers are? If not, I'd recommend not using
the unary & and * operators until you do.
 
J

James Kuyper

Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;

You're trying to initializing j, which is a pointer to an int, with the
value of 10, which is an integer. That's a constraint violation
(6.5.16.1p1). A conforming implementation is required to issue a
diagnostic message - did yours? If so, what did it say?

After issuing the diagnostic, your compiler is free to do anything it
wants with your code. I suspect that what it is doing is converting 10
to a pointer value, and storing that pointer value in j.

You could force it to do that conversion explicitly by inserting an
(int*) before the 10, in which case the constraint violation would go
away. However, the resulting pointer value is implementation-defined. It
might contain a trap representation, in which case the behavior of your
program would still be undefined. Even if it is not a trap
representation, you have no idea where in memory it points at. It
probably does not point at a piece of memory reserved for use by your
program; if it does, there's a small chance it points at the same piece
of memory reserved to store the value of 'i'.

Since you don't know what location in memory j points at, you can't be
sure whether adding 19 to that pointer will have defined behavior; it
probably doesn't.

You're trying to store the result of that addition, which is a pointer
value, into an int object. This is once again a constraint violation,
with the same consequences as the first time.
printf("%d %d\n",j,i);

You're using a %d format specifier, which should be used only for int
values, to print the value of j, which is a pointer. That's yet another
example of undefined behavior.
}

The output is a garbage value (86) on my pc and ideone. Should it not be 29?

The output could have been anything, including the text of the "Star
Spangled Banner" (or nothing at all). That's what "undefined behavior"
means.

Here's correct code that does something similar to what your original
code may have been meant to do:

int i;
int k;
int *j=&k;
*j = 10;
i = *j+19;
printf("%d %d\n", *j, i);
 
B

BartC

rage said:
Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;
i=j+19;
printf("%d %d\n",j,i);
}

The output is a garbage value (86) on my pc and ideone. Should it not be
29?

Assuming you did intend j to be a pointer, try it like this:

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

int main(void)
{
int i;
int *j=malloc(sizeof(int));
*j=10;
i=*j+19;
printf("%d %d\n",*j,i);
}

(The code assumes the malloc() call is successful.)
 
J

John Gordon

In said:
Can someone please help me out on this?
#include<stdio.h>
main()
{
int i;
int *j=10;
i=j+19;
printf("%d %d\n",j,i);
}
The output is a garbage value (86) on my pc and ideone. Should it not be 29?

You declared j as an integer pointer, and initialized it to point at memory
location 10, which very likely contains an unknown value.

As others have said, your compiler should have issued a warning about
this, which would have given you a clue as to what the problem was.
 
L

Les Cargill

rage said:
Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;
i=j+19;
printf("%d %d\n",j,i);
}

The output is a garbage value (86) on my pc and ideone. Should it not be 29?


Your code is broken:

int i;
int k = 10;
int *j = &k;
i=(*j)+19;
printf("%d %d\n",*j,i);

might work as you expect. "int *j;" declares j as "a pointer
to an integer". "j = 10;" make it point to address 10.

you probably don't want that.

From that point on, you're not in Kansas any more.. you're exposing...
<puts on sunglasses>
UNDEFINED BEHAVIOR!
 
K

Keith Thompson

Angel said:
In this line, you're converting an integer value to a pointer. That
is an operation with undefined behavior. (Except if the integer is a
constant value of zero, if I recall right.)

What makes you think there's a conversion there?

The declaration violates a constraint. An initialization has
the same constraints as a simple assignment (N1570 6.7.9p11).
The rules for simple assignment say that if the left hand side has
pointer type, the right hand side must have pointer type (either
a compatible type or void*) or it can be a null pointer constant.

Since

int *j = 10;

doesn't satisfy these constraints, there is no definition of its
behavior. In particular, the standard does not say or imply that the
int value 10 should be converted to int*.

That was the typical behavior for pre-standard versions of C, and
most compilers that don't reject the declaration will generate code
equivalent to:

int *j = (int*)10;

But it's not required.

Note that the behavior of an integer-to-pointer conversion is not
(entirely) undefined. N1570 6.3.2.3 says:

An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity
of the referenced type, and might be a trap representation.

with a footnote:

The mapping functions for converting a pointer to an integer
or an integer to a pointer are intended to be consistent with
the addressing structure of the execution environment.

(But that's not relevant to this code because, as I said, no conversion
is implied.)

[...]
 
K

Keith Thompson

rage said:
Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;
i=j+19;
printf("%d %d\n",j,i);
}

The output is a garbage value (86) on my pc and ideone. Should it not be 29?

The value 86 is not garbage, though the program that produced it is.

First off, "main()" should be "int main(void)". Most compilers will
probably accept "main()", but it's an obsolete form.

int *j = 10;

is a constraint violation. Your compiler should have either produced a
warning or rejected it outright, and you should have told us that. If
your compiler doesn't produce a diagnostic, then it's misbehaving; find
out how to invoke it so that it produces proper diagnostics.

If it's not rejected, the most likely behavior is that the compiler will
treat it as if you had written:

int *j = (int*)10;

which converts the int value 10 to int* and stores it in j. This is
almost certainly a nonsensical thing to do, but it's legal; the result
of the conversion is implementation-defined.

i = j + 19;

Since j is a pointer object, j + 19 performs pointer arithmetic. Given
a pointer value p and an integer value n, the expression p + n assumes
that p points to an element of an array and yields a pointer n elements
past the one that p points to. In other words, pointer arithmetic is
scaled by the size of the pointed-to type.

If sizeof (int) == 4 on your system, then j + 19 is likely to yield a
pointer to a location 76 bytes (19 int objects) past the location that j
points to.

printf("%d %d\n", j, i);

This has undefined behavior. The "%d" format requires an int argument,
but you're giving it an int*. But given a few plausible assumptions,
such as that int and int* happen to have the same size and that
conversions between pointers and integers just reinterpret the
representation without performing any other transformation, it's likely
that it will print

10 89

where 10 is the value of j (10 converted from int to int*, and the
interpreted as if it were an int), and 89 is the value of i
(10 + (4*19), but with several conversions from int to int* and
back again).

The only thing you really *need* to know about this program is that
it's invalid. You have several instances of undefined behavior, and
one constraint violation, requiring a compile-time diagnostic that
*you should not ignore*. The above is a plausible explanation of
the behavior you're seeing -- but it could be completely different
on another system, or on the same system with different options,
or it could be rejected altogether.
 
A

Angel

What makes you think there's a conversion there?

The declaration violates a constraint. An initialization has
the same constraints as a simple assignment (N1570 6.7.9p11).
The rules for simple assignment say that if the left hand side has
pointer type, the right hand side must have pointer type (either
a compatible type or void*) or it can be a null pointer constant.

Since

int *j = 10;

doesn't satisfy these constraints, there is no definition of its
behavior. In particular, the standard does not say or imply that the
int value 10 should be converted to int*.

That was the typical behavior for pre-standard versions of C, and
most compilers that don't reject the declaration will generate code
equivalent to:

int *j = (int*)10;

But it's not required.

Note that the behavior of an integer-to-pointer conversion is not
(entirely) undefined. N1570 6.3.2.3 says:

An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity
of the referenced type, and might be a trap representation.

with a footnote:

The mapping functions for converting a pointer to an integer
or an integer to a pointer are intended to be consistent with
the addressing structure of the execution environment.

(But that's not relevant to this code because, as I said, no conversion
is implied.)

Haha, thanks for clarifying and correcting. Clearly I've been out of C
programming so much that what I know no longer matches with current
standards. I suppose I should go brush up my skills. :)

Anyway, the bottom line to the original poster is "don't mix up integers
and pointers unless you really know what you're doing", yes?
 
K

Keith Thompson

Angel said:
Anyway, the bottom line to the original poster is "don't mix up integers
and pointers unless you really know what you're doing", yes?

Pretty much. Conversions between pointers and integers are problematic
(except for the special case of converting a null pointer constant, such
as a literal 0, to a pointer type, which is well defined).

On the other hand, pointer arithmetic is well defined in most cases:

pointer + integer => pointer
integer + pointer => pointer
pointer - pointer => integer

(except that it doesn't apply to void* or other pointers to incomplete
types, or to function pointers, and going outside the bounds of a single
object is undefined.)
 
R

Ralph Spitzner

[....]

Only scenario I could think of is on a 68k System where
one woud want to stick a function pointer into Address
4, generate a Trap and hope memory wasn't corrupted :p
 
C

Charles Richmond

rage said:
Can someone please help me out on this?

#include<stdio.h>
main()
{
int i;
int *j=10;
i=j+19;
printf("%d %d\n",j,i);
}

The output is a garbage value (86) on my pc and ideone. Should it not be
29?

As others have correctly pointed out, you have violated a dozen or so
constraints.

Using "old style" C (prior to the ISO standards), here is the answer I would
give:

If you add an integer to a pointer, the integer is *scaled* by the size of
the object that the pointer points to. An "int" on your machine must be
four bytes, therefore 19 is multiplied by 4 before adding it to the 10.
Thus you get 86. (4*19+10)

One of the important things to remember here: arithmetic involving pointers
is *scaled*.
 

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,776
Messages
2,569,603
Members
45,187
Latest member
RosaDemko

Latest Threads

Top