I can't figure out how this works.
// This doesn't work (obviously)
char a;
a = "aaa";
// This works
char* a;
a = "aaa";
How come this works ?
Since char type stores only one character or 1 byte number, how can you store more characters in it when you access it through a pointer ?
You're not putting characters into the char*. You're creating an array of characters in a part of memory determined by your compiler, and pointing the char* at the first character of that array.
The array is actually const, so you shouldn't be able to assign it to a non-const pointer. But due to historical reasons, you still can in many C++ implementations. However, it was officially made illegal in C++11.
The second one is a pointer to a string of chars, not a single char. Tutorial.
Related
I'm trying to set a pointer array to a char array in class Tran, however it only applies the first letter of the string. I've tried many other ways but can't get the whole string to go into name.
edit: name is a private variable
char name[MAX_NAME + 1];
Trying to output it using cout << name << endl;
the input is:
setTran("Birth Tran", 1);
help would be appreciated, thank youu
namee[0] == NULL
name[0] = NULL;
These are bugs. NULL is for pointers. name[0] as well as namee[0] is a char. It may work (by work, I mean it will assign the first character to be the null terminator character) on some systems because 0 is both a null pointer constant and an integer literal and thus convertible to char, and NULL may be defined as 0. But NULL may also be defined as nullptr in which case the program will be ill-formed.
Use name[0] = '\0' instead.
name[0] = *namee;
however it only applies the first letter of the string.
Well, you assign only the first character, so this is to be expected.
If you would like to copy the entire string, you need to assign all of the characters. That can be implemented with a loop. There are standard functions for copying a string though; You can use std::strncpy.
That said, constant length arrays are usually problematic because it is rarely possible to correctly predict the maximum required size. std::string is a more robust alternative.
The underlying issue you are trying to assign a const char* to an char* const. When declaring
char name[MAX_NAME + 1];
You are declaring a constant memory address containing mutable char data (char* const). When you are passing a const char* to your function, you are passing a mutable pointer containing constant data. This will not compile. You should be doing a deep copy of the char array by using:
strcpy_s(dst, buffer_size, src);
This copy function will make sure that your array does not overflow, and that it is null terminated.
In order to be able to assign a pointer to a char array, it would need to be allocated on the heap with
char* name = new char[MAX_NAME + 1];
This would allow assigning a char* or char* const to it afterwards. You however need to manage the memory dynamically at this point, and I would advise against this in your case, as passing "Birth Tran" would lead to undefined behaviours as soon as char* const namee goes out of scope.
I recently started learning C++ and came across with the concept of a pointer (which is a variable that stores the address of another variable). However I also came across with char* str = "Hello" and I became confused. So it looks like the of "Hello" is being assigned to the pointer str (which I thought could only store addresses). So can a pointer also store a string?
For future reference you should only use the language tag of the language you're using. C and C++ are two very different languages, and in this case there is a difference.
First the common part: Literal strings like "Hello" are stored by the compiler as arrays. In the case of "Hello" it's an array of six char elements, including the string null terminator.
Now for the part that's different: In C++ such string literal arrays are constant, they can not be modified. Therefore it's an error to have a non-const pointer to such an array. In C the string literal arrays are not constant, but they are still not modifiable, they are in essence read-only. But it's still allowed to have a non-const pointer to them.
And finally for your question: As with all arrays, using them make them decay into a pointer to their first element, and that is basically what happens here. You make your variable str point to the first element in the string literal array.
A little simplified it can be seen like this (in C):
char anonymous_literal_array[] = "Hello";
...
char *str = &anonymous_literal_array[0]; // Make str point to first element in array
The pointer will store the address of the start of the string, therefore the first character. In this case "Hello" is an immutable literal. (Check the difference: Immutable vs constant)
More correctly, a pointer cannot store a string as well as anything, a pointer can point to an address containing data of the pointer's type.
Since char* is a pointer to char, it points exactly to a char.
In this example, the pointer is the address of the first character in the string. This is inherited from C where a "string" is an array of characters terminated by a NULL character. In C and C++, arrays and pointers are closely related. When you do your own memory management, you often create an array with a pointer to the first element of the array. That is exactly what is going on here with the array holding the string literal "Hello".
in c/c++ strings are stored as array of characters. Literal string like "Hello" actually return start of temporary read only character array which hold this string.
A char* variable is a pointer to a single byte(char) in memory. The most common way of handling strings is called a c-style string where the char* is a pointer to the first character in the string and is followed by the rest of the characters in memory. The c-string will always end in a '\0' or null character to signify that you've reached the end of the string ( 'H', 'e', 'l', 'l', 'o', '\0' ).
The "Hello" is called a string literal. What happens in memory is at the very beginning of your program, before anything else is run, the program allocates and sets the memory for the "Hello" string where the other static constants are located. When you write char* str = "Hello"; The compiler knows you're using a string literal and sets str to the location of the first character of that string literal.
But be careful though. All string literals are stored in a portion of memory that you cannot write to. If you try to modify that string, you might get memory errors. To make sure this doesn't happen, when dealing with c-strings, you should always write const char* str = "Hello"; That way the compiler will never allow you to modify that memory.
To have a modifiable string, you will need to allocate and manage the memory yourself. I would suggest using std::string, or have some fun and make your own string class that handles the memory.
The nearest question on this website to the one I have had a few answers that didn't satisfy me.
Basically, I have 2 related questions :
Q. If I do something like :
char a[]= "abcde"; //created a string with 'a' as the array name/pointer to access it.
a[0]='z'; //works and changes the first character to z.
But
char *a="abcde";
a[0]='z'; //run-time error.
What is the difference? There is no "const" declaration, so I should be free to change contents, right?
Q. If I do something like :
int i[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i; //'i' is a pointer to i[0], so I'm incrementing it and want to print 20.
This gives me a compile-time error, and I don't understand why.
On the other hand, this works :
int *i=new int[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i; //Prints 20.
Thanks for the help.
Q
char *a="abcde";
a[0]='z'; //run-time error.
Ans - Here a is pointing to string literal stored in read only location. You cannot modify string literal
Q
int i[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i;
Ans- Array and Pointers are not same thing. Here i is not a pointer.
You need lvalue for increment operand
You can do :
int *p = &i[0];
std::cout<<*++p;
In last case operator new returns a pointer to a allocated memory space, so its possible.
Question 1
The trouble is that it is still const.
A string literal actually has the type char const*.
But when they designed C++03 they decided (unfortunately) that conversion from char const* to char* is not an error. Thus the code:
char *a="abcde";
Actually compiles without error (even though the string is const). BUT the string literal is still a const even though it is being pointed at via a non const pointer. Thus making it very dangerous.
The good news is that most compilers will generate a warning:
warning: deprecated conversion from string constant to ‘char*’
Question 2
cout<<*++i; //'i' is a pointer to i[0], so I'm incrementing it and want to print 20.
At this point i is not a pointer. It's type is still an array.
It is not a valid operation to increment array.
The thing you are thinking about; is that arrays decay into pointers at the drop of a hat (like when you pass them to functions). Unfortunately that is not happening in this situation and thus you are trying to increment an array (which does not make sense).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can't I edit a char in a char*?
char *k ;
void ffill()
{
char *d="ddddd";
*k=*d; //expecting to copy "ddddd" to *k
cout<<k<<"\n";
*d[1]=5; // trying to change array element
cout<<k<<"\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
ffill();
cout<<k<<"\n";
}
procedure fill initializes character array k with help of local variable. I'm not sure it copies "ddddd" variable pointer (that is wrong, because after automatic destruction of d memory is not safe) or it copies value and after this *k is initialized correctly.
How to aces *d array element? Compiler is not happy about *d[1]=5;
(Disclaimer: this answer only covers C++. It is not recommended to ask for both C and C++, as both languages are quite different)
Prologue
char *k ;
This declares a pointer to a character.
"ddddd"
This expression has type char const[6], that is, an array of six constant characters. Expressions of this type can be implicitly converted to a pointer to the first element of the array. The type of that pointer is char const*, that is, a pointer to a constant character. A char const* is not convertible to a char*, because char* permits modification of the character it points to, while char const* doesn't.
char *d="ddddd";
Due to the rules outlined above, this statement is not correct. You should turn on the warnings on your compiler and it will warn you against this (ideally it would actually be an error, not just a warning). It should be char const* d = "ddddd"; if you really want a pointer or char d[] = "ddddd"; if you want an array. The second form doesn't need const because it makes a copy, and thus runs no risk of changing the original data, which is const.
*d
This expression involves the implicit conversion to char const* mentioned above, and then the indirection operator (the *) is applied to it, resulting in an expression of type char const&, that is, a reference to a constant character.
*k
Similar to *d, this performs indirection on a pointer. In this case, k is of type char*, so the resulting expression has type char&.
*k=*d; //expecting to copy "ddddd" to *k
The assignment assigns a single character, because it's assignment from a reference to a constant character into a reference to a character. It ends up assigning the first character of the string to the character pointed by k, which is... wait.
Where does k point to? It was never initialized! This is bound to end in tragedy.
Chapter 1
So, how do we get k to point somewhere? And how do we copy the whole string from d into that space?
To copy the six characters of the d array into k, we need space for six characters. The simplest way of doing this is to just make an array of six characters.
char k[6];
Now, how to copy the six elements? We can use the C library function strcpy, which copies null-terminated strings. This function needs a lot of care to use because:
It requires the source to have a null ('\0') character marking the end; if the source does not have such a character, the behaviour is undefined and anything can happen. This is why the string "ddddd" has six characters and not 5: there's an implicit \0 character at the end that the compiler inserts for you.
It requires the destination to have enough space for the whole source string including the null terminator. If the destination doesn't have enough space, the behaviour is also undefined and anything can happen.
This is how this function could be used to make a copy of the string:
std::strcpy(k, d);
Failure to meet either point #1 or #2 can result in anything, from the program seemingly working (if you're unlucky), to acting randomly in strange way, to simply crashing (if you're lucky).
Epilogue
Man, that was a lot of information. Do C++ programmers have to care about these matters all the time? That must be tiresome.
Well, C++ programmers can use std::string instead of character arrays and get a lot less hassle with this: we can make copies with the assignment operator, we don't need to track the correct sizes, we don't need to care for having the null terminators in place, we don't need to limit the size at compile time, and a bunch of other advantages.
std::string k;
void ffill()
{
std::string d="ddddd";
k = d;
cout<<k<<"\n";
d[1]=5;
cout<<k<<"\n";
}
With C programming langage, you should use an array rather than a pointer (because it may point to a read-only string). For example :
char *k;
void
fill(void)
{
char d[] = "ddddd";
k = d;
d[1] = '5'; // Did you mean '5' ?
}
Like Martinho Fernandes already stated: It seems like you're trying to use 'std:string', instead of char arrays.
char k[20] ; //*k doesn't allocate any memory for you to use.
void ffill()
{
char *d="ddddd"; //This works, since it points to the constant character string in your code. But it can not be altered in any way. (It's a 'const char *')
strcpy(k, d); //This standard function copies the content of one pointer to another.
cout<<k<<"\n"; //Not too sure, but it should work,
k[1]=5; //k is the 'changeable memory, not 'd'.
cout<<k<<"\n";
}
There are several things going on here that you need to be aware of. Let me try to explain:
char *k ;
This line declares a variable called k which is a pointer to a character. However, it is not initialized to point to anything. Trying to use an uninitialized pointer will result in undefined behavior.
void ffill()
{
char *d="ddddd";
This line declares a variable named d which is also a pointer to a character. At the same time, you initialize the pointer to point to a constant character array (also called a c-string) that contains 5 'd' characters and a terminating NULL character (so the array has 6 elements).
*k=*d; //expecting to copy "ddddd" to *k
This line uses the dereference operator (*). This operator copys the character pointed to by d and places it at the address pointed to by k. As I noted above, this will result in undefined behavior since the address in the pointer k has not been initialized.
cout<<k<<"\n";
*d[1]=5; // trying to change array element
First of all, you are trying to assign an int to a char. Both C and C++ allow this, but you probably won't get what you expect. In this case, you are trying to replace the second 'd' character with the character code 5. In ASCII, this is a non-printing character.
Also, since d points to a c-string constant, trying to change its elements results in undefined behavior.
cout<<k<<"\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
ffill();
cout<<k<<"\n";
}
There are some other issues with copying one c-string to another, but this is all the detail I will go into here. As other people mention, using std::string is simpler. However, I also believe that learning how to use c-strings is very educational and can improve your coding skills.
Let's see:
*k=*d; //expecting to copy "ddddd" to *k
This won't copy the "string", only tries to set the memory pointed by k to the first character of d. If it is not initialized, then it will fail badly.
*d[1]=5; // trying to change array element
This will also fail. First of all, this is a double indirection. The d[1] = 5; would be betted, but that would also fail, because the string is most probably stored in read-only memory.
Use string instead.
You need to declare d as an array and not a pointer.:
char d[]
d[1] = '5'; // d is a char array, so did you mean the character '5'?
And change
*k=*d; to k = d; //This will copy the value of the pointer
What is the difference between these two in terms of memory allocation.
char *p1 = "hello";
char p2[] = "hello";
The first one creates a pointer variable (four or eight bytes of storage depending on the platform) and stores a location of a string literal there, The second one creates an array of six characters (including zero string terminator byte) and copies the literal there.
You should get a compiler warning on the first line since the literal is const.
The first one is a non-const pointer to const (read-only) data, the second is a non-const array.
Since the first one is a non-const pointer to const (read-only) data, the second is a non-const array, as Paul said, you can write:
p2[2]='A'; //changing third character - okay
But you cannot write:
p1[2]='A';//changing third character - runtime error!