3

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.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Joe Snikeris
  • 1,150
  • 12
  • 17

5 Answers5

4

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++.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Makes most sense of everything posted here so far! – Pavel Minaev Jul 25 '09 at 01:43
  • 2
    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 Jul 25 '09 at 06:00
3

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
  • 99,783
  • 25
  • 219
  • 289
0

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 :)

Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
  • 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 Jul 25 '09 at 00:50
  • well thats true, I agree with you it is useful only for a learner and useless after that :) – Khaled Alshaya Jul 25 '09 at 00:55
0

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
  • 20,482
  • 11
  • 57
  • 74
0

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

Samvel
  • 11
  • 1