In the following piece of code, to calculate strlen,
int s(const char* str)
{
int count=0;
while(*str++) count++;
return count;
}
You can see that the argument str is const. But, the compiler does not complain when I do a str++. My question is
When passing pointers as arguments to a C function, if is is qualified with const, How can I still perform pointer arithmetic on it? What is const in the above function?
const char* str;
means a non-const pointer to a const data.
char* const str;
means a const pointer to a non-const data.
const char* const str;
means a const pointer to a const data.
The reason for this is that in C++ the variable type declarations are parsed from right to left, which results in that the word "const" always defines the constness of the thing that it's closest to.
It's not declaring the pointer const, it's declaring the thing pointed to as const. Try this:
int s(const char* const str)
With this declaration, you should get a compile error when you modify str.
const char * ch; // non-const pointer to const data
char * const ch; // const pointer to non-constant data.
const char * const ch; // const pointer to const data
Note:
Also
const char * ch;
equals to
char const * ch;
The pointer points to a const char, a read-only character array.
Related
I am writing a code in C++ right now, and I have a dilemma.
EDIT: I added the class relevant definition
_fullName is defined in the class as a private dm(char _fullName)
my class contains the getter method below:
char* getFullName() const { return this->_fullName; }
However, I had in the past cases in which I returned char* with const(const char*)
I can change the getter method to this one:
const char* getFullName() const { return this->_fullName; }
Both versions are compiling but I don't know how to choose.
I would take the second version, but I wonder Why even the version without the const is compiling? shouldn't it give an error when I remove the const keyword, because the function is a CONST member function and therefore the dms are const as well and cannot be returned without the const keyword???
This is the class relevant definition:
class Professional
{
private:
char* _ID;
char* _fullName;
int _age;
char* _profession;
}
First understand what const attached to a member function means. It determines the const-ness of the implicit this used for the member. Given this:
struct S
{
char value[10];
const char *mfn() const { return value; }
};
within the confines of mfn the implicit this is const S *. Furthermore, all references to members obtained therein are also const. In this case, that means value as an expression representation is const char (&)[10] before any further conversion are attached therein.
That's important.
In the correct posted example above there is an automatic conversion to temporary pointer, since const char(&)[10] converts to const char* without objection. However, the following will fail:
struct S
{
char value[10];
char *mfn() const { return value; }
};
The reason this will fail is simply because there is no conversion possible. value, remember, is const char (&)[10], and can only implicitly convert to const char*.
But how could it succeed? Well, consider this:
struct S
{
char *ptr;
char *mfn() const { return ptr; }
};
This will work. The reason is subtle, but obvious once you think about it. ptr is a char*. The attachment of const to this makes that char * const&, not const char *& (there is a difference; the former is a reference to a non-mutable pointer to mutable data, the latter is a reference to a mutable pointer to non-mutable data). Since return ptr is not mutating ptr (or anything else in the object), it is viable as a result.
In short, in your case it works because the pointer you are returning isn't via some implicit conversion from a const underlayment; it's just a value.
You have a few things going on here, in your example of the int num member this is not the same as a char * member.
lets expand your example a bit:
class Professional
{
int* func() const
{
return &myInt; // Fails because it returns a reference to a member variable
}
char* func() const
{
return &myChar; // Fails because it returns a reference to a member variable
}
int* func() const
{
return pInt; // ok because it returns a COPY of the member pointer
}
char* func() const
{
return pChar; // ok because it returns a COPY of the member pointer
}
int myInt;
char myChar;
int *pInt;
char *pChar;
Note: the two pointers getting returned by copy are ok. Its the pointers that are copies not the thing being pointed to. The memory that is pointed to is nothing to do with this class.
As to an answer to your question: there is a rule of thumb that is to apply const as much as possible - this helps to show other users your intent and gains benefits from compiler warnings / errors if a user tries to use your class in a way you did not intend. So in this case pass back a const char *.
Note: See this answer for more specific details here: What is the difference between const int*, const int * const, and int const *?
So I am learning C++ right now, and I just started to get into Pointers, and I thought I would understand the semantics pretty well till iI saw this in one of the recommended solutions to an exercise int the Book I am learning with:
const char* sa = * ( static_cast < const char* const* > (a));
I understand everything aside the const* in the Type Parameter. Why is it there, what does it do?
EDIT: corrected unclear formulation
* in a type means that the type is a pointer to the type on the left side of the asterisk.
const in a type means that the type to the left of const is constant. For an object, const means that the value may not be modified. For a reference, const means that the object may not be modified through the reference.
char is a type that represents an integer encoded narrow character object.
const char is a const char.
const char* is a pointer to a const char.
const char* const is a const pointer to a const char.
const char* const* is a pointer to a const char* const.
Note that the pointer is indirected:
* ( static_cast < const char* const* > (a));
^ indirection operator
When a pointer is indirected, the result is a reference (lvalue) to the pointed object. If a const char* were indirected, the resulting lvalue would have the type const char. Clearly such lvalue couldn't be used to initialize the object const char* sa.
When a const char* const* is indirected, the result will be a reference (lvalue) to an object of type const char* const. Such value can be used to initialize const char* sa.
A simpler example without casts:
const char c; // c cannot be modified
const char* const a = &c; // a points to charcter object c
// a cannot be modified
const char* sa = *a; // sa points to a as well
sa = nullptr; // sa can be modified; it no longer points to a
I know second constant keyword tells function is constant
class Person{
char *name;
int age;
public:
const char* GetName() const;
int GetAge() const;
};
the pointer that you assign the pointer returned by the function, points to a const char
const char* GetName() const;
The first occurence of the const keyword in the above statement is in the data type of the return value of the function GetName(), which is also a constant function.
This means that the value returned by GetName() will be:
of type char
a pointer
a const value
Since the return value will be const, GetName() will recieve a pointer to a constant char value. So if you have:
Person object;
const char* point = object.GetName();
*point will point to a constant char value.
As it has been explained above, it says const pointer. It will work only for const pointers.
const char * p = GetName(); //Compiled successfully
char * p = getName(); //compilation error... however you can remove using const_cast)
const char* reflect that char* is constant. Therefore following line will give error:--
*p = 'c';
However P is not constant here. So you can write like :--
char ch;
p = &ch;
Usually when function returns the value, we are concerned about value (like it should not be modified). I hope it will help.
It means that the function returns pointer to a constant char. Following will be a goodread for usage of const keyword in C++.
http://www.cprogramming.com/tutorial/const_correctness.html
Labelled as homework because this was a question on a midterm I wrote that I don't understand the answer to. I was asked to explain the purpose of each const in the following statement:
const char const * const GetName() const { return m_name; };
So, what is the explanation for each of these consts?
Take them from the right. The one before the ; tells the client this is a design level const i.e. it does not alter the state of the object. (Think of this as a read-only method.)
Okay, now the return value:
const char const *const
This is a constant pointer to okay ... here we go boom! You have an extra const -- a syntax error. The following are equivalent: const T or T const. If you take out a const you get a constant pointer to a constant characters. Does that help?
You have one more const than is syntactically allowed, that code would not compile. Remove the "const" after "char" and before the "*". Also, the last const must come before the function body. It helps to read things like this from right to left.
const char * const GetName() const { return m_name; };
You have a const function (i.e., the function does not alter the state of the class.), which returns a const pointer to a const char.
(1)const char (2)const * (3)const GetName() { return m_name; } (4)const;
The contents of char array is const. This is good when you return pointer of the object member. Since you give pointer to your member for 3rd party, you want to prevent it to be changed from outside.
This form is not used frequently and essentially same as (1)
Our pointer to char array is const, so you can not change where the pointer points too.
it qualifies the GetName() intself, meaning that the method thus not change the class it applied too. Thus it can be called for const object of this type only.
This form typically used as GetName(...) const.
As already mentioned in another answers the trick to "remember" it it read from right to left:
const T * - pointer to const T
T * const - const pointer to T
Edit: Looks like I incorrectly pasted the code into Comeau, or it was edited in the original answer to be correct. In either case I'm preserving the answer below as if the code were incorrect.
Comeau online compiler gives these results:
"ComeauTest.c", line 4: error: type
qualifier specified more than once
const char const * const GetName() {
return m_name; } const;
^
"ComeauTest.c", line 4: warning: type
qualifier on return type is
meaningless const char const * const
GetName() { return m_name; } const;
^
"ComeauTest.c", line 4: error:
declaration does not declare anything
const char const * const GetName() {
return m_name; } const;
What this means is that your statement is malformed.
const char const * const GetName() { return m_name; } const;
The first and second consts mean the same thing. You can't specify the same qualifier more than once so one of these would have to be removed for the code to compile. Both of these consts specify that the values pointed to by the pointer returned by GetName cannot be modified, making code like this invalid:
const char* name = c.GetName();
name[0] = 'a';
The third const specifies that the pointer returned by GetName() itself cannot be modified, but as Comeau points out, this doesn't accomplish anything on a return value because the return value is a copy of the pointer rather than the pointer itself, and can be assigned to a non-const pointer.
The fourth const is misplaced, it should be between GetName and the function body like this:
const char* GetName() const { return m.name; }
This const specifies that no members of the class will be modified during the execution of GetName. Assuming that GetName a member of the class Person, this code would be allowed:
const Person& p;
p.GetName();
Without this const, the above code would fail.
It is possible that you missed "*" symbol before second const keyword.
const char * const * const GetName() const { return m_name; };
So it means that the function returns constant pointer to constant pointer to constant character.
last const:
Function does not change the privates of the class
one after last const:
It's a constant pointer (i.e. the place it points to is constant)
second const:
The function returns a const char (i.e. the content of the char is constant)
First:
No idea?
So to be complete:
The function returns a constant pointer (always same location) to a constant char(always same content) and the function does not modify the state of the class.
const(1) char const(2) * const GetName() { return m_name; } const(3);
const char * const result = aaa.GetNAme();
3 - const method, not allowed to change members nor call any non-const methods.
1 - does not allow to modify inside the pointer, i.e. *result = ..
2 - does not allow to move the pointer, i.e. result = NULL
Given:
const char const * const GetName() const { return m_name; };
The first and second const are equivalent, but only one of them is allowed -- i.e. you can put const before or after the type (char in this case) but only one or the other, not both. Either, however, says that the characters pointed to by the pointer cannot be written to.
The const after the '*' means the pointer returned by the function cannot itself be modified. This is rarely seen on a return type -- what you're returning is a value, which can't be modified in any case (it's normally just assigned to some variable). This can, however, be meaningful in other contexts.
The third const is only allowed on a member function. It says that when this function is called, the this pointer that's received will be a T const * const rather than a T * const, so the member function can only modify static or mutable members of the object, and if it invokes other member functions, they must be const as well. There is, however, a caveat, that it can also cast away the const'ness, in which case it can modify what it sees fit (with the further caveat that if the object was originally defined as const, rather than just having a const pointer to a normal (non-const) object, the results will be undefined).
I often see the following function declaration:
some_func(const unsigned char * const buffer)
{
}
Any idea why the const is repeated before the pointer name?
Thanks.
The first const says that the data pointed to is constant and may not be changed whereas the second const says that the pointer itself may not be changed:
char my_char = 'z';
const char* a = &my_char;
char* const b = &my_char;
const char* const c = &my_char;
a = &other_char; //fine
*a = 'c'; //error
b = &other_char; //error
*b = 'c'; //fine
c = &other_char; //error
*c = 'c'; //error
type declarations should(?) be read RTL. const modifies the thing on its left, but the rule is complicated by the fact that you can write both const T and T const (they mean the same thing).
T * const is a constant pointer to mutable T
T & const would be constant reference to mutable T, except references are constant by definition
T const * is a mutable pointer to constant T
T const & is a reference to constant T
T const * const is constant pointer to constant T
It's a constant pointer to a constant unsigned char. You can't change the pointer nor the thing it points to.
In a declaration like const * const T, the first const (before the *) means that what the pointer points at is const (i.e. it's a pointer to a const T). The const after the * means that the pointer itself is const (i.e. can't be modified to point at anything else).
You can read the declaration from the object being declared outward, so const unsigned char * const buffer is read as: "buffer is a const pointer to a const unsigned char" (this is why const should always being placed after what it modifies--with it before, you have to rearrange things to make the sentence--with it declared as unsigned char const * const buffer, translation to English is simple and straighforward (or perhaps "straightbackward", since you actually read from right to left in this case).
assuming const unsigned char * const
Everyone is correct that its a const pointer to a const unsigned char.
C++ types read mostly right to left unless there are any modifiers on the far left then these read left to right.
This makes it a const pointer to a const value, rather than a mutable pointer to a const value or a const pointer to a mutable value.
const * unsigned char const buffer means that you cannot modify the pointer buffer nor the memory that buffer points to.
A couple of articles to help you understand const correctness in C++:
Wikipedia
Possibility.com