Difference between following statements

D

deepak

Hi,

Can someone please clarify difference between following two declaration?

const char *p;
char* const p;

Thanks,
Deepak
 
P

Paul N

Hi,

Can someone please clarify difference between following two declaration?

  const char *p;

This means p can change, but you can't use it to change the character
pointed at. For example:

p = r; // works if r is a suitable pointer
x = *p; // works if x is a suitable variable
*p = x; // won't work
  char* const p;

This means you can't change p, but you can use it to change the
character pointed at. For example:

p = r; // doesn't work
x = *p; // works if x is a suitable variable
*p = x; // also works if x is a suitable variable

I was going to point you to the C FAQ at http://c-faq.com/ but it
doesn't seem to answer this question. It's still worth a read though.

Hope that helps.
Paul.
 
K

Keith Thompson

deepak said:
Can someone please clarify difference between following two declaration?

const char *p;

declare p as pointer to const char
char* const p;

declare p as const pointer to char

Source: http://cdecl.org/

Or you can install and use the "cdecl" command-line tool:

$ cdecl
Type `help' or `?' for help
cdecl> explain const char *p;
declare p as pointer to const char
cdecl> explain char* const p;
declare p as const pointer to char
cdecl>
 
J

James Kuyper

This means p can change, but you can't use it to change the character
pointed at. For example:

p = r; // works if r is a suitable pointer
x = *p; // works if x is a suitable variable
*p = x; // won't work


This means you can't change p, but you can use it to change the
character pointed at. For example:

p = r; // doesn't work
x = *p; // works if x is a suitable variable
*p = x; // also works if x is a suitable variable

I was going to point you to the C FAQ at http://c-faq.com/ but it
doesn't seem to answer this question. It's still worth a read though.

It's not quite correct to say that you can't do those things, and the
section of the FAQ that Ben referred doesn't go into the relevant issues
either. It would be more accurate to say that any attempt to do those
things is a constraint violation, which requires a diagnostic message.
Making that message mandatory is the main purpose for using 'const' in a
declaration. If you know that a given pointer should not be used to try
to change something, you can insert 'const' in the appropriate part of
the declaration to get the compiler to warn you if your code actually
does attempt to misuse it in that fashion. Either the attempt to change
the corresponding object was a mistake, or the belief that the variable
should not be used to make such changes was a mistake - you'll have to
investigate to determine which one was wrong. But at least, with the
message, you'll know there was a conflict.

However, after having issued a diagnostic, a compiler is still free to
translate your code into a program. If you choose to execute that
program, it's behavior is undefined. That means, among other
possibilities, that the program might in fact change something it should
not have changed (even objects defined as 'const').

You can disable the diagnostic message by casting the pointer to an
appropriate non-const type. Never do this unless you're sure it's both
necessary and correct - consider whether it would be more appropriate to
remove the 'const' from the declaration, rather than casting it away.

It might be perfectly safe to write code that bypasses those warnings
using a cast. However, one thing a cast cannot do for you is allow you
to safely change the contents of an object which is itself defined as
'const' (rather than, for instance, a pointer to 'const'). The behavior
is always undefined if your code attempts that,
 
S

Shao Miller

Can someone please clarify difference between following two declaration?

const char *p;
char* const p;

int main(void) {
const char (* (p));
char (* const (q));

const char (* const (r));
char const (* const (s));

return 0;
}

In the first, the reference type is 'const char' and 'p' is an
unqualified pointer to that type. You can assign to 'p'.

In the second, the reference type is 'char' and 'q' is a const-qualified
pointer to that type. You cannot assign to 'q'. Because there's no
initializer, 'q' in the example code is worse than useless.

In the third and fourth, the reference types are the same: 'const char'.
'r' and 's' are const-qualified pointers to that type. You cannot
assign to either of them, and without initializers, they are both worse
than useless.
 
E

Edward A. Falk

Hi,

Can someone please clarify difference between following two declaration?

const char *p;
char* const p;

In general, the 'const' applies to whatever immediately follows.

From my notes:

const int x = 44; x cannot change
const int *z; *z cannot change
int * const z; z cannot change
const int *const z; z cannot change and *z cannot change

char **s; pointer to pointer to char
const char * * s pointer to pointer to const char
char const * * s pointer to pointer to const char
char * const * s pointer to const pointer to char
char * * const s const pointer to pointer to char
char * const * const s const ptr to const ptr to char

const struct employee {
char *name;
int birthdate;
int job_code;
} a,b; no member or a or b can change

struct employee c,d; but c and d are not const

struct employee {
char *name;
const int birthdate; this member cannot change
int job_code;
};
 
A

Alain Ketterlin

In general, the 'const' applies to whatever immediately follows.

s/follows/precedes/

(placing it at the extreme left is a convenience, and the only case
where it applies to what follows).

[...]
const char * * s pointer to pointer to const char
char const * * s pointer to pointer to const char

We agree, const applies to the char.
char * const * s pointer to const pointer to char
char * * const s const pointer to pointer to char
char * const * const s const ptr to const ptr to char

and, for completeness, the twins:

const char * const * const s
char const * const * const s

where everything is const.

-- Alain.
 
K

Keith Thompson

Shao Miller said:
int main(void) {
const char (* (p));
char (* const (q));

const char (* const (r));
char const (* const (s));

return 0;
}

In the first, the reference type is 'const char' and 'p' is an
unqualified pointer to that type. You can assign to 'p'.

In the second, the reference type is 'char' and 'q' is a const-qualified
pointer to that type. You cannot assign to 'q'. Because there's no
initializer, 'q' in the example code is worse than useless.

In the third and fourth, the reference types are the same: 'const char'.
'r' and 's' are const-qualified pointers to that type. You cannot
assign to either of them, and without initializers, they are both worse
than useless.

In all cases, I think you mean "referenced type" rather than
"reference type".

For a "pointer to FOO" type, "FOO" is the "referenced type".
The term is introduced in N1570 6.2.5p20.

(The phrase "reference type" could be confused with the C++ feature
of that name, something that doesn't exist in C.)
 
S

Shao Miller

In all cases, I think you mean "referenced type" rather than
"reference type".

For a "pointer to FOO" type, "FOO" is the "referenced type".
The term is introduced in N1570 6.2.5p20.

(The phrase "reference type" could be confused with the C++ feature
of that name, something that doesn't exist in C.)

Quite right; thanks! As a nit-pick, I believe that "referenced type"
was in C89/C90, then wasn't in C99, and now has returned for C11.
 
J

James Kuyper

In general, the 'const' applies to whatever immediately follows.

s/follows/precedes/

(placing it at the extreme left is a convenience, and the only case
where it applies to what follows).

[...]
const char * * s pointer to pointer to const char
char const * * s pointer to pointer to const char

We agree, const applies to the char.

In both cases **s is what cannot change, and **s follows the keyword const.

In this case, *s is what cannot change, and *s follows the keyword const.

In this case, s cannot change, because it is what follows the keyword
'const'.

In this case, *s cannot change, because that's what follows the first
'const', and s itself also cannot change, because that's what follows
the second 'const'.

If you believe that the word "follows" should be replaced by "precedes",
I presume that either you disagree with my descriptions, or you apply
the rule in a different manner. Could you explain?
 
S

Shao Miller

const char *p;
char* const p;

In general, the 'const' applies to whatever immediately follows.

s/follows/precedes/

(placing it at the extreme left is a convenience, and the only case
where it applies to what follows).

[...]
const char * * s pointer to pointer to const char
char const * * s pointer to pointer to const char

We agree, const applies to the char.

In both cases **s is what cannot change, and **s follows the keyword const.

In this case, *s is what cannot change, and *s follows the keyword const.

In this case, s cannot change, because it is what follows the keyword
'const'.

In this case, *s cannot change, because that's what follows the first
'const', and s itself also cannot change, because that's what follows
the second 'const'.

If you believe that the word "follows" should be replaced by "precedes",
I presume that either you disagree with my descriptions, or you apply
the rule in a different manner. Could you explain?

Reading the type as English can sometimes involve working backwards.
For the last example, 's' is a "constant pointer to a constant pointer
to a character," which is the opposite order to the syntactical elements
as they appear. This could explain the discrepancy.
 
A

Alain Ketterlin

Shao Miller said:
[...]
In general, the 'const' applies to whatever immediately follows.

s/follows/precedes/ [...]
char * const * s pointer to const pointer to char

In this case, *s is what cannot change, and *s follows the keyword const.
[...]

Yes but we're talking about types, and const qualifies the type that
precedes, which is "char *". How would you call "*s" in your example?
Let's call this a "potential expression". Then, const applies to the
type that precedes and to the potential expression that follows
(ignoring other const qualifiers appearing, e.g., char const * const s).
Reading the type as English can sometimes involve working backwards.
For the last example, 's' is a "constant pointer to a constant pointer
to a character," which is the opposite order to the syntactical
elements as they appear. This could explain the discrepancy.

Exactly. The C++ faq suggest reading right-to-left to understand pointer
declarations with const.

-- Alain.
 
K

Keith Thompson

Shao Miller said:
On 2/25/2013 16:46, Keith Thompson wrote: [...]
In all cases, I think you mean "referenced type" rather than
"reference type".

For a "pointer to FOO" type, "FOO" is the "referenced type".
The term is introduced in N1570 6.2.5p20.

(The phrase "reference type" could be confused with the C++ feature
of that name, something that doesn't exist in C.)

Quite right; thanks! As a nit-pick, I believe that "referenced type"
was in C89/C90, then wasn't in C99, and now has returned for C11.

It's in C90, C99, N1256, and N1570. (I presume it's in the released
2011 standard; my copy isn't handy.)
 
J

James Kuyper

Shao Miller said:
On 02/25/2013 03:05 PM, Alain Ketterlin wrote:
(e-mail address removed) (Edward A. Falk) writes:
[...]
In general, the 'const' applies to whatever immediately follows.

s/follows/precedes/ [...]
char * const * s pointer to const pointer to char

In this case, *s is what cannot change, and *s follows the keyword const.
[...]

Yes but we're talking about types, ...

No, I'm talking about expressions. Since you were talking about types,
that would explain the discrepancy. You may find it easier to think
about 'const' in terms of the type it modifies. I find it easier to
think about it in terms of the expressions that it turns into constraint
violations.
... and const qualifies the type that
precedes, which is "char *". How would you call "*s" in your example?

I'd call it an lvalue expression, potentially referring to an object,
and it is precisely such an expression whose presence as the left
operand of an assignment or compound assignment expression, or as the
only operand of an increment or decrement expression, that would violate
a constraint because of the preceding 'const' keyword.
 
J

John Bode

Hi,

Can someone please clarify difference between following two declaration?

const char *p;
char* const p;

Thanks,
Deepak

In the first case, p is a pointer to a const char; you can modify p
(set it to point to a different thing), but you cannot modify
what p points to.

In the second case, p is a const pointer to a non-const char; you
can modify what p points to, but you cannot modify p (cannot set
it to point to a different thing).

Since attempting to modify a string literal invokes undefined behavior,
many people recommend declaring a pointer to it as const char *, such
as

const char *str = "string literal";

If you try to modify the contents of the literal through str, the compiler
will complain.
 
P

Paul N

It's brief, but it answers it.  What do you think is missing?  (I'm
talking of http://c-faq.com/ansi/constptrconst.html i.e. section 11.9.)

Ah, I thought it was in the FAQ somewhere, but at a quick look I
couldn't find it. As the question is about pointer declarations, one
might expect it to be either in Section 1 - Declarations and
Initializations - or Section 4 - Pointers - but it doesn't seem to
appear in either of these, even as a reference to an answer elsewhere.
 
J

James Kuyper

Ah, I thought it was in the FAQ somewhere, but at a quick look I
couldn't find it. As the question is about pointer declarations, one
might expect it to be either in Section 1 - Declarations and
Initializations ...

It is - see question 1.20 (the answer cross references 11.9)
 
A

army1987

Can someone please clarify difference between following two declaration?

<nitpick>Contrary to what you seem to imply in the subject line,
declarations are not statements. (This means that, as IIRC was mentioned
somewhere recently, `if (something) int i;` is a syntax error.)</nitpick>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top