What's the difference between &C::c and &(C::c)?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
8
down vote

favorite












Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?









share|improve this question























  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago














up vote
8
down vote

favorite












Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?









share|improve this question























  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago












up vote
8
down vote

favorite









up vote
8
down vote

favorite











Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?









share|improve this question















Test code in below and I put the output info in comment.
I was using gcc 4.8.5 and Centos7.2.



#include <iostream>
#include <cstdio>

class C

public:
void foo()
printf("%p, %pn", &C::c, &(C::c)); // output value is 0x4, 0x7ffc2e7f52e8
std::cout << &C::c << std::endl; // output value is 1

int a;
int c;
;

int main(void)

C co;

printf("%pn", &C::c); // output value is 0x4
std::cout << &C::c << std::endl; // output value is 1

// printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'

co.foo();

return 0;



  1. According to C++ operator Precedence,:: operator have higher precedence than & operator. I think &C::c is equal to &(C::c), but the output says no. Why are they different?


  2. &(C::c) causes compile error in main but not in foo function,why is that?

  3. The value of &C::c is different in printf and std::cout, why is that?






c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago









melpomene

54.1k54084




54.1k54084










asked 3 hours ago









Xianggang ZENG

483




483











  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago
















  • You cannot printf a pointer to member value. %p is for regular pointers only.
    – n.m.
    2 hours ago






  • 1




    @n.m. Even worse, %p is for void * only.
    – melpomene
    2 hours ago















You cannot printf a pointer to member value. %p is for regular pointers only.
– n.m.
2 hours ago




You cannot printf a pointer to member value. %p is for regular pointers only.
– n.m.
2 hours ago




1




1




@n.m. Even worse, %p is for void * only.
– melpomene
2 hours ago




@n.m. Even worse, %p is for void * only.
– melpomene
2 hours ago












4 Answers
4






active

oldest

votes

















up vote
5
down vote



accepted










C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



printf("%pn", static_cast<void *>(&(C::c)));



The relevant part of the standard is [expr.unary.op], saying:




The result of the unary & operator is a pointer to its operand.
The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







share|improve this answer






















  • @M.M Not if you do it in foo. See the rest of my answer.
    – melpomene
    1 hour ago










  • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
    – Xianggang ZENG
    1 hour ago










  • @XianggangZENG Thanks, edited.
    – melpomene
    1 hour ago










  • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
    – melpomene
    1 hour ago










  • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
    – melpomene
    1 hour ago

















up vote
1
down vote













While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



Since &C::c is actually not null is implicitly converted to bool with value true or 1






share|improve this answer





























    up vote
    0
    down vote













    First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



    So you see an error with:



    // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


    If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



    And let's run



    #include <iostream>
    #include <cstdio>

    class C

    public:
    void foo()
    printf("%p, %p, this=%pn", &C::c, &(C::c), this);

    int a;
    int c;
    ;

    int main(void)

    C co;
    co.foo();
    return 0;



    The output is:



    0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
    // 0x4 + this == 0x7ffee78e47f4
    // see reference


    And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



    That's all.



    Some reference: C++: Pointer to class data member "::*"



    Full description: https://en.cppreference.com/w/cpp/language/pointer






    share|improve this answer






















    • In C::c, the C can only be a class or namespace name (never an instance)
      – M.M
      1 hour ago

















    up vote
    -2
    down vote













    Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



    Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




    Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



    The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



    For further discussion of how to print a pointer-to-member, see this answer.




    Q2: The code &(C::c) does not form a pointer-to-member as explained above.



    Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




    An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



    • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

    • to form a pointer to member (7.6.2.1), or

    • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



    When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



    When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






    share|improve this answer






















    • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
      – melpomene
      2 hours ago










    • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
      – melpomene
      2 hours ago










    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52940237%2fwhats-the-difference-between-cc-and-cc%23new-answer', 'question_page');

    );

    Post as a guest






























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    5
    down vote



    accepted










    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







    share|improve this answer






















    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago














    up vote
    5
    down vote



    accepted










    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







    share|improve this answer






















    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago












    up vote
    5
    down vote



    accepted







    up vote
    5
    down vote



    accepted






    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]







    share|improve this answer














    C++ distinguishes two forms of operands to the & operator, lvalues in general and (qualified) identifiers specifically. In &C::c the operand of & is a qualified identifier (i.e. just a name) whereas in &(C::c) the operand is a general expression (because ( cannot be part of a name).



    The qualified identifier form has a special case: If it refers to a non-static member of a class (like your C::c), & returns a special value known as a "pointer to member of C". See here for more information about member pointers.



    In &(C::c) there is no special case. C::c is resolved normally and fails because there is no object to get a c member of. At least that's what happens in main; in methods of C (like your foo) there is an implicit this object, so C::c actually means this->c there.



    As for why the output is different for printf vs. cout: When you try to print a member pointer with <<, it is implicitly converted to a bool, yielding false if it's a null pointer and true otherwise. false is printed as 0; true is printed as 1. Your member pointer is not null, so you get 1. This is different from normal pointers, which are implicitly converted to void * and printed as addresses, but member pointers cannot be converted to void * so the only applicable overload of operator<< is the one for bool. See https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt#Notes.



    Note that technically your printf calls have undefined behavior. %p takes a void * and you're passing it pointers of different types. In normal function calls the automatic conversion from T * to void * would kick in, but printf is a variable-arguments function that provides no type context to its argument list, so you need a manual conversion:



    printf("%pn", static_cast<void *>(&(C::c)));



    The relevant part of the standard is [expr.unary.op], saying:




    The result of the unary & operator is a pointer to its operand.
    The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant member m of some class C with type T, the result has type “pointer to member of class C of type T” and is a prvalue designating C​::​m.
    Otherwise, if the type of the expression is T, the result has type “pointer to T” [...]








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 1 hour ago

























    answered 2 hours ago









    melpomene

    54.1k54084




    54.1k54084











    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago
















    • @M.M Not if you do it in foo. See the rest of my answer.
      – melpomene
      1 hour ago










    • ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
      – Xianggang ZENG
      1 hour ago










    • @XianggangZENG Thanks, edited.
      – melpomene
      1 hour ago










    • @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
      – melpomene
      1 hour ago










    • @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
      – melpomene
      1 hour ago















    @M.M Not if you do it in foo. See the rest of my answer.
    – melpomene
    1 hour ago




    @M.M Not if you do it in foo. See the rest of my answer.
    – melpomene
    1 hour ago












    ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
    – Xianggang ZENG
    1 hour ago




    ”try to print a pointer with <<,it's implicitly converted to a bool"。 I try int b = 1; std::cout << &b << std::endl;, it output an address not just 1.
    – Xianggang ZENG
    1 hour ago












    @XianggangZENG Thanks, edited.
    – melpomene
    1 hour ago




    @XianggangZENG Thanks, edited.
    – melpomene
    1 hour ago












    @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
    – melpomene
    1 hour ago




    @M.M The one in main is commented out ... or at least it was before you edited OP's code. Now it no longer matches the question. Sigh.
    – melpomene
    1 hour ago












    @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
    – melpomene
    1 hour ago




    @M.M That's the second question. The first question is why the output is different for &C::c vs &(C::c). (The third question is why the output is different for printf vs cout.)
    – melpomene
    1 hour ago












    up vote
    1
    down vote













    While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



    Since &C::c is actually not null is implicitly converted to bool with value true or 1






    share|improve this answer


























      up vote
      1
      down vote













      While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



      Since &C::c is actually not null is implicitly converted to bool with value true or 1






      share|improve this answer
























        up vote
        1
        down vote










        up vote
        1
        down vote









        While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



        Since &C::c is actually not null is implicitly converted to bool with value true or 1






        share|improve this answer














        While the expression &C::c result in a pointer to member c the expression &(C::c) yield the address of the member variable c. The difference you're seeing in the output is that std::cout involve a bool implicit conversion that tells you whether the pointer is null or not.



        Since &C::c is actually not null is implicitly converted to bool with value true or 1







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 hours ago

























        answered 2 hours ago









        Jans

        5,01111926




        5,01111926




















            up vote
            0
            down vote













            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer






            share|improve this answer






















            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago














            up vote
            0
            down vote













            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer






            share|improve this answer






















            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago












            up vote
            0
            down vote










            up vote
            0
            down vote









            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer






            share|improve this answer














            First, you can not access the int c by using &(C::c) outside a class. &(C::c) means the memory address of "c of instance C", somewhat &(this->c) here. However your c is not a static member of class C and there is no C instance. You can not access int x = C::c outside, either.



            So you see an error with:



            // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c'


            If you have a static int c, then C::c outside the class is OK, because no instance is needed here.



            And let's run



            #include <iostream>
            #include <cstdio>

            class C

            public:
            void foo()
            printf("%p, %p, this=%pn", &C::c, &(C::c), this);

            int a;
            int c;
            ;

            int main(void)

            C co;
            co.foo();
            return 0;



            The output is:



            0x4, 0x7ffee78e47f4, this=0x7ffee78e47f0
            // 0x4 + this == 0x7ffee78e47f4
            // see reference


            And for std::out: the << &C::c is implicit-casted to bool, so true is 1 you saw. You can treat &C::c as an offset of c in C, it is unusable without a C instance.



            That's all.



            Some reference: C++: Pointer to class data member "::*"



            Full description: https://en.cppreference.com/w/cpp/language/pointer







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 2 hours ago

























            answered 2 hours ago









            shawn

            2,420616




            2,420616











            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago
















            • In C::c, the C can only be a class or namespace name (never an instance)
              – M.M
              1 hour ago















            In C::c, the C can only be a class or namespace name (never an instance)
            – M.M
            1 hour ago




            In C::c, the C can only be a class or namespace name (never an instance)
            – M.M
            1 hour ago










            up vote
            -2
            down vote













            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






            share|improve this answer






















            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago














            up vote
            -2
            down vote













            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






            share|improve this answer






















            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago












            up vote
            -2
            down vote










            up vote
            -2
            down vote









            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.






            share|improve this answer














            Q1: There is special meaning to the syntax of & followed by an unparenthesized qualified-id. It means to form a pointer-to-member. Furthermore, there is no other way to form a pointer-to-member.



            Note: The section C++17 [expr.prim.paren]/1 says that redundant parentheses can be inserted around any expression "except otherwise indicated", however this situation seems to be intended as "otherwise indicated".




            Q3: In both cases where you write printf("%pn", &C::c);, &C::c is a pointer-to-member. The %p format specifier is only for void * so this causes undefined behaviour, and the program output is meaningless.



            The code cout << &C::c; outputs a pointer-to-member via operator<<(bool val), since there is implicit conversion from pointer-to-member to bool (with result true in all cases), see [conv.bool]/1.



            For further discussion of how to print a pointer-to-member, see this answer.




            Q2: The code &(C::c) does not form a pointer-to-member as explained above.



            Now, the code C::c is in the grammatical category id-expression. (Which is qualified-id and unqualified-id). An id-expression has some restrictions on its use, [expr.prim.id]/1:




            An id-expression that denotes a non-static data member or non-static member function of a class can only be used:



            • as part of a class member access in which the object expression refers to the member’s class or a class derived from that class, or

            • to form a pointer to member (7.6.2.1), or

            • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.



            When we are inside the C::foo function, the first of those bullet points applies. The code is the same as &c but with unnecessary qualification. This has type int *. You could output this with std::cout << &(C::c); which would show a memory address, the address of this->c.



            When we are in the main function , none of the three bullet points apply and therefore the &(C::c) is ill-formed.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 1 hour ago

























            answered 2 hours ago









            M.M

            102k10106224




            102k10106224











            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago
















            • The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
              – melpomene
              2 hours ago










            • Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
              – melpomene
              2 hours ago















            The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
            – melpomene
            2 hours ago




            The compiler doesn't say "no", it says invalid use of non-static data member 'C::c'.
            – melpomene
            2 hours ago












            Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
            – melpomene
            2 hours ago




            Please remove the // from the line // printf("%pn", &(C::c)); // compile error, invalid use of non-static data member 'C::c' and try again.
            – melpomene
            2 hours ago

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52940237%2fwhats-the-difference-between-cc-and-cc%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            Long meetings (6-7 hours a day): Being “babysat” by supervisor

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            Confectionery