What's the difference between &C::c and &(C::c)ï¼Â
Clash 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;
- 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? &(C::c)
causes compile error in main but not in foo functionï¼Âwhy is thatï¼Â- The value of
&C::c
is different inprintf
andstd::cout
, why is thatï¼Â
c++
add a comment |Â
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;
- 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? &(C::c)
causes compile error in main but not in foo functionï¼Âwhy is thatï¼Â- The value of
&C::c
is different inprintf
andstd::cout
, why is thatï¼Â
c++
You cannotprintf
a pointer to member value.%p
is for regular pointers only.
â n.m.
2 hours ago
1
@n.m. Even worse,%p
is forvoid *
only.
â melpomene
2 hours ago
add a comment |Â
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;
- 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? &(C::c)
causes compile error in main but not in foo functionï¼Âwhy is thatï¼Â- The value of
&C::c
is different inprintf
andstd::cout
, why is thatï¼Â
c++
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;
- 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? &(C::c)
causes compile error in main but not in foo functionï¼Âwhy is thatï¼Â- The value of
&C::c
is different inprintf
andstd::cout
, why is thatï¼Â
c++
c++
edited 1 hour ago
melpomene
54.1k54084
54.1k54084
asked 3 hours ago
Xianggang ZENG
483
483
You cannotprintf
a pointer to member value.%p
is for regular pointers only.
â n.m.
2 hours ago
1
@n.m. Even worse,%p
is forvoid *
only.
â melpomene
2 hours ago
add a comment |Â
You cannotprintf
a pointer to member value.%p
is for regular pointers only.
â n.m.
2 hours ago
1
@n.m. Even worse,%p
is forvoid *
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
add a comment |Â
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 memberm
of some classC
with typeT
, the result has type âÂÂpointer to member of classC
of typeT
â and is a prvalue designatingCâÂÂ::âÂÂm
.
Otherwise, if the type of the expression isT
, the result has type âÂÂpointer toT
â [...]
@M.M Not if you do it infoo
. See the rest of my answer.
â melpomene
1 hour ago
âÂÂtry to print a pointer with<<
ï¼Âit's implicitly converted to a bool"ã I tryint 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 inmain
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 forprintf
vscout
.)
â melpomene
1 hour ago
 |Â
show 2 more comments
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
add a comment |Â
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
InC::c
, theC
can only be a class or namespace name (never an instance)
â M.M
1 hour ago
add a comment |Â
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.
The compiler doesn't say "no", it saysinvalid 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
add a comment |Â
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 memberm
of some classC
with typeT
, the result has type âÂÂpointer to member of classC
of typeT
â and is a prvalue designatingCâÂÂ::âÂÂm
.
Otherwise, if the type of the expression isT
, the result has type âÂÂpointer toT
â [...]
@M.M Not if you do it infoo
. See the rest of my answer.
â melpomene
1 hour ago
âÂÂtry to print a pointer with<<
ï¼Âit's implicitly converted to a bool"ã I tryint 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 inmain
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 forprintf
vscout
.)
â melpomene
1 hour ago
 |Â
show 2 more comments
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 memberm
of some classC
with typeT
, the result has type âÂÂpointer to member of classC
of typeT
â and is a prvalue designatingCâÂÂ::âÂÂm
.
Otherwise, if the type of the expression isT
, the result has type âÂÂpointer toT
â [...]
@M.M Not if you do it infoo
. See the rest of my answer.
â melpomene
1 hour ago
âÂÂtry to print a pointer with<<
ï¼Âit's implicitly converted to a bool"ã I tryint 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 inmain
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 forprintf
vscout
.)
â melpomene
1 hour ago
 |Â
show 2 more comments
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 memberm
of some classC
with typeT
, the result has type âÂÂpointer to member of classC
of typeT
â and is a prvalue designatingCâÂÂ::âÂÂm
.
Otherwise, if the type of the expression isT
, the result has type âÂÂpointer toT
â [...]
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 memberm
of some classC
with typeT
, the result has type âÂÂpointer to member of classC
of typeT
â and is a prvalue designatingCâÂÂ::âÂÂm
.
Otherwise, if the type of the expression isT
, the result has type âÂÂpointer toT
â [...]
edited 1 hour ago
answered 2 hours ago
melpomene
54.1k54084
54.1k54084
@M.M Not if you do it infoo
. See the rest of my answer.
â melpomene
1 hour ago
âÂÂtry to print a pointer with<<
ï¼Âit's implicitly converted to a bool"ã I tryint 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 inmain
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 forprintf
vscout
.)
â melpomene
1 hour ago
 |Â
show 2 more comments
@M.M Not if you do it infoo
. See the rest of my answer.
â melpomene
1 hour ago
âÂÂtry to print a pointer with<<
ï¼Âit's implicitly converted to a bool"ã I tryint 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 inmain
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 forprintf
vscout
.)
â 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
 |Â
show 2 more comments
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
add a comment |Â
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
add a comment |Â
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
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
edited 2 hours ago
answered 2 hours ago
Jans
5,01111926
5,01111926
add a comment |Â
add a comment |Â
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
InC::c
, theC
can only be a class or namespace name (never an instance)
â M.M
1 hour ago
add a comment |Â
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
InC::c
, theC
can only be a class or namespace name (never an instance)
â M.M
1 hour ago
add a comment |Â
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
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
edited 2 hours ago
answered 2 hours ago
shawn
2,420616
2,420616
InC::c
, theC
can only be a class or namespace name (never an instance)
â M.M
1 hour ago
add a comment |Â
InC::c
, theC
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
add a comment |Â
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.
The compiler doesn't say "no", it saysinvalid 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
add a comment |Â
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.
The compiler doesn't say "no", it saysinvalid 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
add a comment |Â
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.
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.
edited 1 hour ago
answered 2 hours ago
M.M
102k10106224
102k10106224
The compiler doesn't say "no", it saysinvalid 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
add a comment |Â
The compiler doesn't say "no", it saysinvalid 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
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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 forvoid *
only.â melpomene
2 hours ago