0

I want to learn c++, and here is my beginner question.

#include <iostream>
#include <string>

using std::cout;
using std::endl;

struct student{
    struct address{
        int no;
        std::string city;    //problem is here
    };

    char grade;
    int num;
    address *addr;
};

int main(){

    student st1;
    student *pSt1 = &st1;

    pSt1->grade = 'A';
    pSt1->num = 1234;

    pSt1->addr->no = 123;
    pSt1->addr->city = "Imladris";

    return 0;
}

It crashes, but if I change std::string city like this:

struct student{
    struct address{
        std::string city;   // here
        int no;
    };

    char grade;
    int num;
    address *addr;
};

It doesn't crash and returns 0... No errors nor warnings in either case. Maybe, there is no need to use a pointer here but as I said, I am learning c++. This is a sample code about pointers/structures.

I know how to fix it but I'd like to understand why it breaks. I change the declaration order of string city and it doesn't crash. Why?

sokkyoku
  • 2,161
  • 1
  • 20
  • 22
  • 4
    Compile with warnings and listen to your compiler. – Nelfeal Aug 26 '16 at 12:55
  • 3
    And explain what "works" and "does not work" mean (compile error, program crash, unexpected results...) – SJuan76 Aug 26 '16 at 12:56
  • 1
    What does it mean that "it works or not" ?? show us compiler errors or sth like this – Krzysztof Bargieł Aug 26 '16 at 12:57
  • Why are you using pointer here `address *addr;` and here `student *pSt1 = &st1;` actually? – Holt Aug 26 '16 at 13:00
  • i mean first code crashes, but if i change its declaration order, it doesn't crash. Process returned 0. Also there is no error or warning in either case. – justaquestion Aug 26 '16 at 13:08
  • 1
    @justaquestion Learn how to use your compiler. Any decent C++ compiler will give you a warning if you use the `Wall` option. – Nelfeal Aug 26 '16 at 13:16
  • 1
    @justaquestion I second @Nelxiost on this, when programming in C or C++, *always* compile with `-Wall` and `-Wextra`. Warnings might seem annoying because "I can just ignore them" but they almost always point out that your code won't work as expected and tell you where to look. – sokkyoku Aug 26 '16 at 13:41

2 Answers2

1

You just came across the term Undefined behavior. The end result of your code is compiler and platform dependent. Dereferencing a pointer which value is not specified is (as mentioned here) considered to be one of these cases where you are not able to predict the outcome of an operation.

Community
  • 1
  • 1
Adrian Jałoszewski
  • 1,695
  • 3
  • 17
  • 33
0

Keep your nested structure but add this to your member variable declaration:

address *addr = new address();

Or a better way is to use it as user @tobi303 mentioned: Don't declare it as a pointer, just an instance of address instead:

address addr;

But use it this way:

pSt1->addr.no = 123; // set
pSt1->addr.city = "Imladris"; // set
Community
  • 1
  • 1
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104
  • 1
    would be worth mentioning that there is absolutely no need to make the member `addr` a pointer – 463035818_is_not_an_ai Aug 26 '16 at 13:00
  • @tobi303 it's mentioned in the question - "Maybe, there is no need to use pointer here but as i said, i learn c++". It's probably an exercise from a book. – Adrian Jałoszewski Aug 26 '16 at 13:49
  • 1
    @AdrianJałoszewski I think when OP says "maybe no need for pointer" he refers to `pSt1` which is also not needed. The fact that `address` does not need to be a pointer is maybe less obvious. If it is taken from a book, well.. also in books you can find nonsense sometimes – 463035818_is_not_an_ai Aug 26 '16 at 13:53
  • There are a very few need to use `new` in C++. This statement: `address *addr = new address();` is an invite to memory leak, manual memory management, and it is not an idiomatic way to deal with pointers with ownership semantics. – Amadeus Aug 26 '16 at 14:04