a pointer that points to itself

D

dough

Is it possible in C to declare and initialize a pointer that points to
itself? Why or why not?
 
W

Walter Roberson

Sure, but of what use would it be?

I suspect that 'dough' means "in a single statement". The use of it
would be to answer homework questions.

I have a solution that compiles and executes without problem with
any warning level I throw at it. It does raise some subtle language
points.
 
P

Peter Nilsson

Walter said:
I suspect that 'dough' means "in a single statement". The use of it
would be to answer homework questions.

I have a solution that compiles and executes without problem with
any warning level I throw at it.

I suspect it's done so rarely that compiler writers can't justify the
time and code needed to detect the questionable code.
It does raise some subtle language points.

A generic circular list containing 1 element may well have a pointer
that
points to itself. If you're talking about expressions like...

p = ((cast) p)->next;

....then this has been discussed before in csc.
 
S

Skarmander

Walter said:
I suspect that 'dough' means "in a single statement". The use of it
would be to answer homework questions.

I have a solution that compiles and executes without problem with
any warning level I throw at it. It does raise some subtle language
points.
The point it raises is this: may an initializer for a variable reference
the address of that variable?

The point is fairly academic, since it's hard to imagine a situation
where this is both useful and not rewritable as initialization after
declaration. Note that we're not talking about nonsense like
int j = j + 1;
which is undefined in any case since j is used uninitialized. But how about
ptrdiff_t y = &y - &y;

Another poorly conceived homework question, then -- somehow these things
always ask students to invoke undefined behaviour or technically
require them to find out whether they will.

S.
 
T

tanmoy87544

I am confused. Why would you think it is undefined? The scope of a
variable starts immediately after the declarator is done, it has
nothing to do with initialization. int j = j + 1 and int j[j] are
undefined due to different reasons; in fact, one can contrive
situations where the latter statement is completely well-defined.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

tedu said:
Sure, but of what use would it be?
actually no. The types would be incompatible.
You can't do int *foo = &foo; &foo has type int**.
 
P

Peter Nilsson

Nils said:
actually no. The types would be incompatible.
You can't do int *foo = &foo; &foo has type int**.

But you can change int for another type which makes it work.
 
V

Villy Kruse

I am confused. Why would you think it is undefined? The scope of a
variable starts immediately after the declarator is done, it has
nothing to do with initialization. int j = j + 1 and int j[j] are
undefined due to different reasons; in fact, one can contrive
situations where the latter statement is completely well-defined.


"After the declarator", is that at the following semicolon or comma,
or immediately after the name itself but before a possible equals sign?


Villy
 
K

Keith Thompson

I am confused. Why would you think it is undefined? The scope of a
variable starts immediately after the declarator is done, it has
nothing to do with initialization. int j = j + 1 and int j[j] are
undefined due to different reasons; in fact, one can contrive
situations where the latter statement is completely well-defined.

It's undefined because we don't know what you're talking about. You
need to provide context when you post a followup; we can't necessarily
see the article to which you're replying.

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

This advice has been posted here well over 1000 times.
 
F

Flash Gordon

Nils said:
actually no. The types would be incompatible.
You can't do int *foo = &foo; &foo has type int**.

Actually, if you pick the correct types, you don't have a problem with
types and pointers to pointers.
 
P

pete

Flash said:
Actually, if you pick the correct types, you don't have a problem with
types and pointers to pointers.

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
void *pointer = &pointer;

if (pointer == &pointer) {
printf("&pointer is %p\n", pointer);
printf("&pointer is %p\n", (void *)&pointer);
}
return 0;
}

/* END new.c */
 
S

Skarmander

> Skarmander restored context when he copied:
The point it raises is this: may an initializer for a variable
reference the address of that variable?

The point is fairly academic, since it's hard to imagine a
situation where this is both useful and not rewritable as
initialization after declaration. Note that we're not talking about
nonsense like

int j = j + 1;

which is undefined in any case since j is used uninitialized. But
how about

ptrdiff_t y = &y - &y;
>>
I am confused. Why would you think it is undefined? The scope of a
variable starts immediately after the declarator is done, it has
nothing to do with initialization. int j = j + 1 and int j[j] are
undefined due to different reasons; in fact, one can contrive
situations where the latter statement is completely well-defined.
I know
int j = j + 1;
is undefined for a different reason. I explicitly said it wasn't what we
were talking about (but now we are :)

I also know that in turn is completely different from
int j[j];
which involves getting tricky with overloading. This is unlike
everything else we've discussed because there are two distinct 'j's here.

This still doesn't answer my question, because that asks about the scope
of a variable *while in the initialization part of the declaration*. If
you happen to know that's defined, great. Quote the relevant parts of
the standard that imply this, please. (But like I said, the point is
fairly academic, so you won't see me crying if this is forever left
unresolved.)

S.
 
S

S.Tobias

Skarmander said:
Skarmander restored context when he copied:
The point it raises is this: may an initializer for a variable
reference the address of that variable?

The point is fairly academic, since it's hard to imagine a
situation where this is both useful and not rewritable as
initialization after declaration. Note that we're not talking about
nonsense like

int j = j + 1;

which is undefined in any case since j is used uninitialized. But
how about

ptrdiff_t y = &y - &y;
I am confused. Why would you think it is undefined? The scope of a
variable starts immediately after the declarator is done, it has
nothing to do with initialization. int j = j + 1 and int j[j] are
undefined due to different reasons; in fact, one can contrive
situations where the latter statement is completely well-defined.
I know
int j = j + 1;
is undefined for a different reason. I explicitly said it wasn't what we
were talking about (but now we are :)

I also know that in turn is completely different from
int j[j];
which involves getting tricky with overloading. This is unlike
everything else we've discussed because there are two distinct 'j's here.

This still doesn't answer my question, because that asks about the scope
of a variable *while in the initialization part of the declaration*. If
you happen to know that's defined, great. Quote the relevant parts of
the standard that imply this, please. (But like I said, the point is
fairly academic, so you won't see me crying if this is forever left
unresolved.)

6.2.1#7. Initializer is not part of a declarator.
Some useful examples are in C++ Standard.
 
S

Sunil

A small example to understand "pointer points to itself"

int main()
{
char *p = "xyz";

printf(" P:%s &P:%p \n", p , &p);

p = &p;

printf(" P:%p &P:%p \n", p , &p);


return 0;
}

result: P: xyz &P: 0xbfffec44
P: 0xbfffec44 &P: 0xbfffec44
 
F

Flash Gordon

Lawrence said:
However there is no type for which this works. If your pointer have type
TYPE * then a pointer to it has type TYPE **. Since an object in C can
only have one type it can't be both TYPE * and TYPE ** at once.

However there is a similar question for which C does have an answer: "Is
it possible in C to declare and initialize a pointer that points to
THE FIRST BYTE of itself?"

That can be done by for example

char *ptr = (char *)&ptr;

or perhaps

void *ptr = &ptr;

A pointer to the pointer object can be recreated from these by converting
the value back to the correct type (char ** and void ** respectively).

It was this last example I was thinking of. Personally I would consider
it as pointing to the object although I do accept that it needs to be
converted back before it is used.

Or you could use a struct:
struct ltyp {
struct ltyp *node;
};
struct ltyp ltyp_ptr = { &ltyp_ptr };

So part of the struct is initialised as a pointer to the struct, which
is the same as a pointer to the first element of the struct.
 
L

Lawrence Kirby

But you can change int for another type which makes it work.

However there is no type for which this works. If your pointer have type
TYPE * then a pointer to it has type TYPE **. Since an object in C can
only have one type it can't be both TYPE * and TYPE ** at once.

However there is a similar question for which C does have an answer: "Is
it possible in C to declare and initialize a pointer that points to
THE FIRST BYTE of itself?"

That can be done by for example

char *ptr = (char *)&ptr;

or perhaps

void *ptr = &ptr;

A pointer to the pointer object can be recreated from these by converting
the value back to the correct type (char ** and void ** respectively).

Lawrence
 
R

Robert Gamble

pete said:
/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
void *pointer = &pointer;

if (pointer == &pointer) {
printf("&pointer is %p\n", pointer);

ITYM "pointer is %p\n"
printf("&pointer is %p\n", (void *)&pointer);
}
return 0;
}

/* END new.c */

The obvious example, however it is quite debatable (and has been
debated very much so, no need to start again now) as to whether
"pointer" *points* to anything at all (being a pointer to void).

Robert Gamble
 
T

tanmoy87544

Villy said:
"After the declarator", is that at the following semicolon or comma,
or immediately after the name itself but before a possible equals sign?

The declarator is whatever declares the identifier. One can get
formal, but it is easier to say that the declarator ends whenever the
parts to do with its type (not value or implementation; for things
other than stuff that refers to objects and functions, e.g. tags and
labels, there is no conceptual issue) are done. Some examples are
probably easier. In char z[3] = {0,0,0}, x; the scope of x starts
after x and of z after the [3]. The initializer is not part of the
declarator, nor are independent declarations following it. I do hate
to use terms like before a possible = sign because that is a bad way to
think: if you write int f (enum {a = 0, b = 1}); the scope of f still
starts after the closing parenthesis, even though there are equal signs
before it (The example is bad, but not incorrect). I know you meant
the = sign that gives it its initial value, but since C is a strongly
typed language, it is much easier to think of the distintion between
type and value than low level lexical analysis.

There is an aspect that makes the informal discussion above incomplete:
one could argue that after the closing bracket in char a[] = "abc", the
type of a is not yet known, it is only after initialization that we
know it is char[4]. This is a special case because of all incomplete
types only incomplete array types can actually complete them allowing
the apparent definition of objects of such types. The formal rules
specify that even in this case, the declarator ends at the closing
bracket. Because of this you could argue that we should always be
formal, but, at least in C, the formalism tries to capture a
distinction that exists in most programmers' mind; and, it comes out
naturally in explanations.

It is for this reason in my previous post I was contrasting int j = j +
1; versus int j[j]. In the first case, the second j is after the first
j has come in scope and evaluates it. Since the j does not have a
value at this stage, the evaluation is undefined. In int j[j], by
contrast, the scope of the first j has not yet begun when the second j
is used, so it refers to something else altogether! It is usually
undefined, not because j is evaluated before it is given a value, nor
because the array dimension does not have an integral type, but rather
because it refers to an identifier which does not exist! If you write,
for example,
enum {j = 3}; {int j[j];}
then the int j[j] is perfectly well defined and means int j[3]. What
happened is the new j has not yet come into scope, but the scope of the
previous j has not ended, so we just get that meaning of j. Note the
scope rules: the very similar example
enum {j = 3}; {int j = j + 1; }
is truly undefined; you do not get the effect of int j = 4 (or rather,
since it is undefined, anything, including this, might happen) because
the initializer is in the scope of the new j and the old j is hidden.

So what has this got to do with examples like whether
ptrdiff_t d = &d - &d;
is undefined? Well, let us see why it could be undefined. As the
second example with the construction `int j = j + 1' shows the j in the
initializer refers to the newly defined j, similarly, the new d should
refer to the newly defined d, the one without a value yet. Somebody
has already provided a quotation from the standard, and I do not go
into that.

Next we need to know whether we can evaluate &d when d does not have a
value. The answer to this was not doubted by anyone in the discussion,
think {int x; ptrdiff_t d = &x - &x;}, though one could again ask about
quotation from the standard. Similar questions about the validity of
the subtraction and the initialization are actually completely explicit
in the standard. So, I was pointing out that there was no reason to
suspect undefined behaviour: or at least, none that I could see.

I apologize for my previous post being sans context. The admonition
not to use google default must have slipped by me in my careless quick
perusal.
 

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,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top