views:

119

answers:

4

This is a question from the most recent version of Stroustrup's "The C++ Programming Language".

I've been mulling this over in my head for the past couple days.

The only thing I can come up with, (and this is probably incorrect) is something like this:

int* f(int n) {
  int* a = &a - n * sizeof(int*);
  return a;
}

My intent is to get the address of something higher up on the stack. Does this make any sense? Does anyone else have any other answers? Remember, this is in Chapter 5 (pointers, arrays, and structures) so the answer shouldn't involve something later on in the book.

A: 

I think it is a correct way. Just you need to take care of many things :)

First, you don't need sizeof because n will be multiplied by the size of a. Basically you have to choose the right type of the pointer to get the address you want on the stack.

int*  a = &a - n; // so if n==1 => a = &a - (1*4)
char* b = &b - n; // so if n==1 => b = &b - (1*1)

Second, you have to take care of endianess.

Also, I am not sure if I forgot something :)

AraK
you forgot one thing: It's undefined behavior. You're not allowed to do pointer arithmetics beyond the bounds of the original array (where non-array types are considered arrays of a single element) :)
jalf
well thats true, I agree with you it is useful only for a learner and useless after that :)
AraK
+3  A: 

The only (barely) reasonable case I know of is when you want to pass a pointer to the object itself to its constructor. For example, say you have a cyclic linked list node:

class Node
{
public:
    Node(Node* next): next(next) {}
private:
    Node* next;
};

and you want to create a single-element cyclic list on the stack. You can do this:

Node n(&n);

A few other examples that aren't really practical (i.e. I don't see why you'd need that sort of thing), but otherwise valid:

int n = sizeof(n);
void* p = &p;
Pavel Minaev
"Node(Node* next): next(next) {}" line is very subtle, i like that solution :)
Johannes Schaub - litb
Although slightly reminiscent of the "spam" sketch :-)
Steve Jessop
A: 

First off, there is no guarantee about which direction the stack grows. Your code assumes it grows down, but it could also grow up (that is, to lower addresses). Also, there are things that get put on the stack that you may not be aware of (return address, stack frame, registers, etc.) and not "jumping" past when trying to grab things higher up on the stack.

What are you ultimately trying to do?

Jim Buck
In fact, there's no guarantee there is even a stack...
Pavel Minaev
I'm trying to find a reason for using a name in its own initializer. The example I gave was an attempt at such.
Joe Snikeris
+3  A: 

Some example i use very often in C code

C *c = (C*) malloc(sizeof *c);
...
free(c);

It involves pointers and structures. Surely, new frees you from having to use that idiom by saying new C instead in C++.

Johannes Schaub - litb
Makes most sense of everything posted here so far!
Pavel Minaev
Wouldn't sizeof(C) be more clear?
Joe Snikeris
No, because if you change the type of `c`, you'll need to change it in two places, and might accidentially miss the one inside `sizeof` (and it won't be a compile-time error). This way you only have to change type in one place.
Pavel Minaev
Good point. I agree.
Joe Snikeris