I have code:
char* s="abc";
I have a question, what's datatype of a variable in this code?
datatype of s is int
s is string?
So, if datatype of s is int, why cout<<s is "abc"?
The type of s is what the variable is declared to be, nothing else. It is pointer to char, or char*. It points to the first element of a read-only char array, which is why it should really be const char*. In fact, the conversion to char* is deprecated in C++.
The data type is char * (character pointer). It internally contains an integer (the size depends on the processor architecture that you are targeting). It shows up as "ABC" because the << operator is overloaded to display character pointers as strings. If you want to see the integer value, cast it to void *.
Let's ratiocinate.
If s had type int when its declaration would contain type specifier int or some typedef name (a user defined alias for int) that equivalent to int. For example
int s;
or
typedef int MyPersonalType;
MyPersonalType s;
The same way if s had type std::string it would be declared like
std::string s;
Neither the first nor the second is used in the declaration of s.
s is declared like
char* s;
So it has type char * that is it is a pointer to character. Moreover s is initialized by a string literal
char* s="abc";
In this case s is initialized by the address of the first character of the string literal.
So when you use statement
std::cout << s;
this string literal is outputed.
Take into acccount that this record
char* s="abc";
is valid in C. In C++ you have to specify also qualifier const
const char* s="abc";
because string literals are immutable.
"abc" is a literal consisting of the three characters a, b, and c followed by a null terminator.
It can be assigned to a const char*. You can also assign it to a char* but that is dangerous since you cannot modify the contents of the literal.
cout contains an overload that will track along the input pointer until it reaches the null terminator; outputting the characters as it goes.
So, s is modelling a sting of characters.
Related
What is the difference between these two string initializations in c++?
i get the same output in both the programs.
Program 1
void main(){
string a = "hello";
cout<<a;
}
program 2
void main(){
string a = (char *)"hello";
cout<<a;
}
"hello" is a string literal. Its type is
const char[N], where N is the size of the string [...] including the null terminator.
So in this case, the type is const char[6]. Note the const.
Now std::string can be constructed (constructor 5 in the link) from a const char*. Again, note the const.
In C++, you can pass a non-const object into a function that expects a const. In your case, your cast (char *) removes the const, but then immediately puts the const back on in the constructor call.
So basically, no difference. They will compile to exactly the same thing.
A few additional notes:
casting away const-ness is very dangerous. If you had actually tried to change anything in the char array, your program would have had Undefined Behaviour.
using namespace std; is widely considered to be bad practice.
void main() is not a valid signature for the main function; it must return an int.
Using C-style casts in C++ can also be considered a bad practice - it is harder to spot in code, and C++ provides safer equivalents for more specific situations: const_cast, static_cast, dynamic_cast, and (the most dangerous) reinterpret_cast.
Nothing actually, that additional char * type casting is not needed.
In both the cases copy initialization is done.
string (const char* s);
read more on copy initialization
std::string is a typedef for a specialization of basic_string class templated on a char (objects that represent sequences of characters).
The expression string a = "hello" corresponds to a stream of characters whose size is allocated statically.
Short, simple and typesafe std::cout is a typedef of ostream class templated on standard objects (provides support for high-level output operations).
cout means "the standard character output device", and the verb << means "output the object".
cout << a; sends the string like a stream to the stdout.
char * are special pointers to a constant character, they point to ASCII strings e.g.:
const char * s = "hello world";
The expression (char *)"hello" corresponds to a char * pointer, where you are casting away const, but then the constructor immediately puts the const back on the call.
cout, therefore, will print a string because it has a special operator for char * wich it will treat as a pointer to (the first character of) a C-style string that outputs strings.
char* or const char*, cout will treat the operand as a pointer to (the first character of) a C-style string, and prints the contents of that string:
Are strings defined as
string s="Hello";
is of type const char[] of size 6?
If it is of type const char[] then how am I able to do such thing like
s[0]='i'; ??
In
std::string s = "Hello";
the type of the right-hand side is const char[6]. The five characters (not including the terminating null character) are copied elsewhere by the std::string object's constructor. That is why you are able to modify s later.
The type of a string literal is const char [N].
But when you write string s = "Hello";, s is not a literal. It's simply an object of type std::string.
The only literal here is "Hello", thus you can't do "Hello"[1] = 'a';.
Assume a function with one parameter of const char* type. When I use a string when calling that function, nothing goes wrong! I would expect that you could only input characters included in the ASCII, for example c or dec 68, but it seem otherwise. Take a look at the code below...
void InitFunction(const char* initString)
{
std::cout << initString;
}
int main()
{
InitFunction("Hello!");
}
When you run the code, no problem, warnings, or errors appear. I did some more testing on this as you can see from the following...
void InitFunction(char initString)
{
std::cout << initString;
}
int main()
{
InitFunction("Hello!"); // compiler error on this line
}
This compiles with an error since Hello! cannot be converted into char. I tried another test, but instead used const char as the function parameter type. The code still compiles with an error. But when I add * to the function parameter type, then everything compiles fine! It appears to me that the const is also necessary.
To my understanding of pointers, the function is asking for a pointer, and the pointer is identified as being a character. But this raises three problems for me.
First, Hello! is not in the form of a pointer. I would expect at least to have to use the reference operator (&).
Second, Hello! is not a char type.
And third, why do we need to include the const?
Am I missing something here? Do pointers and characters work in ways that I don't know?
"Hello!" is a const char array of characters. Arrays are treated like a pointer, they decay to a pointer when used in a function call as an argument. The C++ standard specifies this in order to be compatible with the way that the C language standard specifies arrays are to be treated.
By the way this array decay to a pointer happens with other cases where an array is being used where a pointer or the address operator could be used such as an assignment statement. See also Arrays are Pointers?
So "Hello!" will be put into the argument list of InitFunction() as a pointer which points to where the compiler has stored the array of characters with the terminating zero character added. When the compiler generates the code for the function call, the pointer to the array of characters used as an argument to the function is const char *, a pointer to a char which is const and should not be changed.
When you have the function prototype as InitFunction(const char *), the compiler is fine with a function call such as InitFunction("Hello!");. What you are doing is providing a const char * that points to "Hello!".
However if you remove the const then since "Hello!" is a const the compiler complains. The compiler complains because a const variable is being used in a function call whose argument list is non-const indicating that the function may change what the pointer is pointing to. Since "Hello!" is not supposed to be changed, since it is const, the compiler issues an error.
If you remove the asterisk, change const char * to const char, then since "Hello!" is a char array which the compiler then decays into a pointer to the first element of the array, the compiler complains as you are trying to use a pointer for an argument that is not a pointer. In this alternative the problem is the actual data type, char versus char * is the problem.
The following lines of code would also be acceptable:
const char *p = "Hello!"; // create a pointer to an series of characters
char x1[] = "Hello!"; // create an array of char and initialize it.
char *p2 = x1; // create a pointer to char array and initialize it.
char *p3 = x1 + 2; // create a pointer to char array and initialize it with address of x1[2].
InitFunction (p); // p is a const char *
InitFunction (x1); // x1 decays to a char *
InitFunction (p2); // p2 is a char *
InitFunction (p3); // p3 is a char *
InitFunction (x1 + 3); // called with address of x1[3].
Note also C++ has an actual character string type, string, that results in a dynamic character text string whose underlying physical memory layout normally includes a pointer to an array of characters. The C style array of characters that is labeled a string is not the same thing as the C++ string type.
the function is asking for a pointer
Correct.
and the pointer is identified as being a character
No, a pointer is a not a character. A pointer is a pointer. This pointer points to one or more characters, i.e. an array of characters. And that's exactly what your string literal is.
First, Hello! is not in the form of a pointer.
Yes, it is. The string literal "Hello!" has type const char[7] and this decays to a pointer.
I would expect at lest to have to use the reference operator (&).
That's the address-of operator. You don't always need it to get a pointer. Example: this.
Second, Hello! is not a char type.
No, but each constituent character is.
And third, why do we need to include the const?
Because the string literal "Hello!" has type const char[7]. Dropping the const would violate const-correctness and is therefore not permitted.
This throws an error since Hello! cannot be converted into char.
That's right. A char is one byte. The string "Hello!" is not one byte. It is a string.
A C-string is typically/conventionally/usually provided in const char* form.
You should read the chapter in your book about this subject as it's a fundamental of the language. It has nothing to do with ASCII (text encodings are irrelevant to storing a sequence of bytes).
So this article is discussing the use of declaring a string literal like const char* foo = "foo" it ends with the claim:
const char *foo = "foo";
is almost never what you want. Instead, you want to use one of the following forms:
For a string meant to be exported:
const char foo[] = "foo";
For a string meant to be used in the same source file:
static const char foo[] = "foo";
For a string meant to be used across several source files for the same library:
__attribute__((visibility("hidden"))) const char foo[] = "foo";
My understanding here is that const char* const foo = "foo" is equivalent to const char foo[] = "foo" simply because we're talking about a C-string pointer that can never be changed to point at anything else, whereas const char* foo = "foo" could be used to point at any other C-String.
Is this an accurate synopsis? Always use either const char* const or const char[]?
Let's get pedantic here.
char const * const p_foo = "foo";
The above defines a {constant} pointer to the {constant} character literal "foo". The pointer is to the single first character of the character literal.
const char bar[] = "bar";
The above defines a character array.
The character array is *read-only".
The character array is the length of the text literal "bar" plus a
nul terminator (4 characters).
The contents of the text literal are copied into the array. (The
compiler may optimize this step away).
Fundamentally, you have the difference between a pointer to the first character of a literal and an array.
The pointer is pointing to a single character. Incrementing the pointer may not point to a valid entity (since it is not an array, but a pointer to a single datum). There is an underlying assumption that the pointer can be incremented to the next character.
With an array you know that there are more than one character sequentially in memory (provided the array is of length 2 or more). You don't know if there is a terminating nul in the sequence (collection). You can assume that, but an array of characters does not guarantee that.
Usages
With the array declaration, the length of the text is known at compile time.
With the pointer declaration, you would need to use strlen to determine the length of the text at run-time. The run-time code doesn't know the length of the target data string; only a length of 1 can be guaranteed.
Sometimes, using static and const can help the compiler optimize.
For example:
static const char moo[] = "moo";
allows the compiler to access the text directly without creating an array variable and copying the text into the variable.
In a function that receives a pointer to a character, you can't guarantee that the pointer points to a valid location (the content of the pointer can be invalid).
Each declaration has its benefits and side-effects.
The choice is yours.
As Thomas Matthews' answer states both a const char* and a const char* const are pointers, and a const char[] is an array.
But as justified here there are 3 problems with using pointers:
Memory for the pointer's storage is required
The indirection incurred by the pointer is required
A pointer requires separate storage of an end pointer for the array or an array size
Ultimately as justified in the link:
The simple answer is that when declaring a variable you should prefer a const char[].
I do agree that an array decays into a pointer when being evaluated but there are a few functionalities that come only with an array. For example when you declare an array you have additional information as to what the size of the array is.
Also, for the fixed array case, memory is allocated specifically for foo. So you are allowed to change the contents of the array like you usually can and the array is destroyed, deallocating memory when it runs out of scope (typical local variable).
When you define it as a pointer, the compiler places foo into read-only memory, and then points to it (usually). Note that this is why most cases constant strings are defined as char* and even the compiler would warn you when you set it as a non constant pointer.
#include <iostream>
int main()
{
char* a = "foo";
return 0;
}
This code would throw you a warning like:
ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
char* a = "foo";
and any change you try to make to the string would typically lead to a segmentation fault.
I have a program which search through an array to find a word match
char *mywords []={"Dog","Cat","etc"};
string search;
cout<<"enter a word to search"<<endl;
cin>>search;
for(int n=0;n<3;n++)
{
if(search==mywords[n])
{
cout<<mywords[n]<<"found"<<endl;
}
}
It works but I am wondering
why it doesn't work when I change the part: string search; to char *search=new char; or char search[4]; it never finds the word
what's the different between char* word("Dog"); and string word("Dog"); .
FIRST QUESTION:
a) why it doesn't work when I change the part
When you use char*, the expression:
search == mywords[n]
Is comparing two pointers of type char*, and not the actual zero-terminated strings pointed to by those pointers.
When you use std::string, on the other hand, the overloaded operator == that accepts an std::string object and a const char* pointer is picked, and proper string comparison is performed.
Besides, keep in mind that you always have to delete objects allocated with new, or you will have a memory leak. This is just another reason why using std::string is preferable.
SECOND QUESTION:
b) what's the different between char* word("Dog"); and string word("Dog");
In the first case, you are initializing a pointer word to point to the first character of the string literal "Dog" - notice, that the type of word should be const char*, and not char*; this implict conversion is deprecated in C++03 and illegal in C++11.
In the second case, you are constructing an object word of type std::string and passing the "Dog" string literal in input to std::string's constructor. The constructor will, in turn, allocate a separate buffer where to copy the original string literal passed as an argument.