-5

i have checked many programming languages(Java,Erlang,python etc..)but i found C/C++ rly hard to learn.Simply because i think its not rational sometimes;

ex1:

    #include <iostream>

    int main() {

     int ar1 = {1,2,3};
     int *p1 = ar1;

     char *msg = "message";

     std::cout << "addr: " << p1 << std::endl ;//prints the array address

     std::cout << "value: " << *p1 << std::endl ;//prints the first element


     std::cout << "addr: " << msg << std::endl ;//prints "message" , wtf why not    the addr?how can i get its address?

     std::cout << "value: " << *msg << std::endl ;//prints the first character


    }

ex2:

    #include <iostream>

    int main() {

     int n1 = 5;
     int *p1 = &n1;

     int &r1 = *p1; // why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...



     }

can you please explain me these examples?i cant go on studying Cplusplus without resolving these things.

Thanks for your time.

  • 4
    I'd bet money that neither of those examples actually compiles without errors. – Graham Borland Jul 20 '12 at 15:33
  • @Graham Borland if you managed to bet anyone you would have won some money – CKKiller Jul 20 '12 at 15:34
  • 1
    @ChristopherKenney Please stay away from that book. Have a look at the [book guide](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – pmr Jul 20 '12 at 15:35
  • The line in ex1 `int *p1 = ar1;` will at least generate a warning. – Ed Heal Jul 20 '12 at 15:36
  • 6
    I disagree entirely with the close votes. This is something that trips up new people. That is: the intersection of inconsistent syntax + big concepts like pointers and references. – Doug T. Jul 20 '12 at 15:39
  • 4
    often, stackoverflow close/negative voting is like: "devotee: Father, Father, are you sure Jesus really lived? priest: What a question? How dare you ask that? Get out". A question can be downvoted if this is ambigous, 'givemecode' type etc.. but don't understand why it gets downvoted if genuine questions are asked which seem to 'hurt' the sentiments of programmer's professional knowledge – PermanentGuest Jul 20 '12 at 15:43
  • 3
    @PermanentGuest: I bet it has to do with edits and different states of the question. Two of the answers are completely unrelated to the question that is now being shown. – David Rodríguez - dribeas Jul 20 '12 at 15:55
  • @DavidRodríguez-dribeas - I agree - Edits are for correcting typos and for clarification - not changing the question. – Ed Heal Jul 20 '12 at 16:15
  • @DavidRodríguez-dribeas yeah that was my fault. I will try to revert the edits I made or vote to close. There's really too much being asked here for one question. – Doug T. Jul 20 '12 at 17:06

3 Answers3

6

Question 1:

char *msg = "message";
std::cout << "addr: " << msg << std::endl ;
//prints "message" , wtf why not    the addr?

This is an artefact of the language's historical evolution from C, where strings are conventionally represented by an array of characters, or a pointer to such an array. To support this, << has an overload taking char const *, which treats it as a pointer to a string and prints the string contents.

You can avoid confusion by using the std::string class to represent strings, and avoid C-style strings except in the (very rare) circumstances where they're useful.

how can i get its address?

You could convert it to a generic pointer:

std::cout << "addr: " << static_cast<void*>(msg) << std::endl;
                         ^^^^^^^^^^^^^^^^^^

Question 2:

int n1 = 5;
int p1 = &n1;

That doesn't compile, since &n1 is an address, and so can only be used to initialise a pointer, not an int. I'll assume you meant:

int *p1 = &n1;

int &r1 = *p1; 
// why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...

Because references aren't pointers, and aren't initialised with an address. A reference must be initialised with a (valid) object, and becomes an alias for that object. *p1 is an object of type int, and so can be used to initialise a reference to int.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
4

The & symbol can be confusing to new people in C++. This is because the & can have multiple meanings.

This:

int* p1 = &n1;

Means take the address of n1 and store it in a pointer to int. p1 is a pointer, holding the address of n1.

This:

int &r1 = *p1;

means create a special type of variable called a reference. (In C++ a reference is really just an alias for something else). r1 is told to alias the value at *p1. *p1 means follow the pointer p1 and get the underlying value. In this case, we know p1 points to n1 so we know here that r1 is a reference to n1. Meaning if I do:

r1 = 5;

And then

std::cout << n1;

The output would be 5

& can also mean the binary and operator. Which is a whole different thing that you're not asking about here.

Doug T.
  • 64,223
  • 27
  • 138
  • 202
  • +1 for answering the real question in ex2 and not hiding behind a compiler error for what is probably a typo in the question. – tinman Jul 20 '12 at 15:37
  • 1
    And FWIW, in `int &r1 = *p1;`, the `&` is not the `&` operator (I should say, it's neither the unary nor the binary `&` operator). It's part of the declaration syntax. Same goes for the `*` in `int *p1 = &n1;`. – Steve Jessop Jul 20 '12 at 15:55
2

A large part of the problem is that your examples are mostly wrong.

First example:

 int ar1 = {1,2,3};
 int *p1 = ar1;

To be correct, this needs to be;

int ar1[] = {1, 2, 3};
int *p1 = ar1;

In this case, things are pretty simple: under most circumstances (including this one) the name of an array evaluates to the address of the beginning of that array (i.e., the type of value you'd assign to a pointer). The primary exception is when you use the array as an operand of the sizeof operator, so sizeof(ar1) would give the actual size of the array (3 *sizeof(int)), not the size of a pointer.

In your second example:

 int n1 = 5;
 int p1 = &n1;

 int &r1 = *p1; // why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...

You're right -- this doesn't make any sense, and a properly functioning compiler shouldn't compile it as-is. What you apparently want is something like this:

int n1 = 5;
int *p1 = &n1;   // p1 is a pointer to int, holding address of n1

int &r1 = *p1;   // r1 is a reference to int, referring to what p1 points at (n1).

As far as printing things out goes, it's pretty simple: how any type gets printed out is purely a decision made by the people who wrote the library. They decided that it made the most sense that when you pass a pointer to char, that it would assume you wanted to print the string that pointed at. For other pointer types, they decided to print out the value of the pointer itself. None of this is really about the language proper though -- it's just a decision somebody made because it was what made sense to them.

If you have an array of char/pointer to char and want to print out the address instead of the characters its points at, you typically cast it to a pointer to void:

 char *msg = "message";

 std::cout << static_cast<void *>(msg);

As to why they chose this, I think it's pretty simple: because when people say cout << mystring, they usually want the content of the string printed out. That's normally restricted to strings because (nearly) everybody agrees about how to print out the contents of a string, but not so much when it comes to things like the contents of an array of int, double, etc.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111