Reputation: 1140
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.
Upvotes: 3
Views: 563
Reputation: 11
Consider an array of integral type that should hold its size in the first element:
// clang++ --std=c++11 initializer.cpp -o initializer
#include <iostream>
using namespace std;
void Print(int* array) {
cout << "array has " << *array << " elements" << endl;
for(int count {*array}; count; --count) {
cout << *++array << endl;
}
}
int main(int, char* []) {
{
int elements[] {sizeof(*elements), 1, 2, 3};
*elements = sizeof(elements) / *elements - 1;
Print(elements);
}
cout << "---" << endl;
{
int elements[] {sizeof(*elements)};
*elements = sizeof(elements) / *elements - 1;
Print(elements);
}
return 0;
}
Output:
./initializer
array has 3 elements
1
2
3
---
array has 0 elements
P.S. Example in GitHub: Chapter 8: Exercise 9.3
Upvotes: 0
Reputation: 506925
An example I use very often in C code is:
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++.
Upvotes: 4
Reputation: 20726
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?
Upvotes: 0
Reputation: 96859
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 :)
Upvotes: 0
Reputation: 101565
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;
Upvotes: 3