Joe Snikeris
Joe Snikeris

Reputation: 1140

TCPL 5.9.9 (C++): Where would it make sense to use a name in its own initializer?

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

Answers (5)

Samvel
Samvel

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

Johannes Schaub - litb
Johannes Schaub - litb

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

Jim Buck
Jim Buck

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

Khaled Alshaya
Khaled Alshaya

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

Pavel Minaev
Pavel Minaev

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

Related Questions