This question already has answers here:
What is the type of string literals in C and C++?
(4 answers)
Closed 9 years ago.
I'm learning C and today I stuck with the "strings" in C. Basically I understand that there is no such thing like string in C.
In C strings are an array characters terminated with \0 at the end.
So far so good.
char *name = "David";
char name[] = "David";
char name[5] = "David";
This is where confusing starts. Three different ways to declare "strings". Can you provide me with a simple examples in which situations which one to use. I've read a lot tutorials on the web but still can't get the idea.
I read this How to declare strings in C question on stackoverflow but still can't get the difference..
First one char *name = "David"; is string literal and is resides in read only section of memory. You can't do any modification to it. Better to write
const char *name = "David";
Second one char name[] = "David"; is a string of 6 chars including '\0'. Modification can be done.
char name[5] = "David"; invoke undefined behavior. "David" is a string of 6 chars (including terminating '\0'). You need an array of 6 chars to store it.
char name[6] = "David";
Further reading: C-FAQ 6. Arrays and Pointers.
This link provides a pretty good explanation.
char[] refers to an array, char* refers to a pointer, and they are not the same thing.
char a[] = "hello"; // array
char *p = "world"; // pointer
According to the standard, Annex J.2/1, it is undefined behavior when:
—The program attempts to modify a string literal (6.4.5).
6.4.5/5 says:
In translation phase 7, a byte or code of value zero is appended to
each multibyte character sequence that results from a string literal
or literals.
Therefore you actually need an array of six elements to account for the NUL character.
In the first example, you declare a pointer to a variable:
// A variable pointer to a variable string (i.e. an array of 6 bytes).
char *pName = "David";
At this time, you can modify the 6 bytes occupied by 'D', 'a', 'v', 'i', 'd', '\0':
pName[0] = 'c';
*pName = 'c';
*(pName+0) = 'c';
strcpy(pName, "Eric"); // Works well
But ONLY those 6 bytes:
// BUG: Will overwrite 2 random bytes located after \0 in RAM.
strcpy(pName, "Fredrik");
The pointer can be altered runtime to point to another variable string e.g.
pName = "Charlie Chaplin";
Which then can be modified
pName[0] = 'c';
*pName = 'c';
*(pName+0) = 'c';
// OK now, since pName now points to the CC array
// which is 16 bytes located somewhere else:
strcpy(pName, "Fredrik");
As stated by others, you would normally use const char * in the pointer cases, which also is the preferred way to use a string. The reason is that the compiler will help you from the most common (and hard-to-find) bugs of memorytrashing:
// A variable pointer to a constant string (i.e. an array of 6 constant bytes).
const char *pName = "David";
// Pointer can be altered runtime to point to another string e.g.
pName = "Charlie";
// But, the compiler will warn you if you try to change the string
// using any of the normal ways:
pName[0] = 'c'; // BUG
*pName = 'c'; // BUG
*(pName+0) = 'c'; // BUG
strcpy(pName, "Eric");// BUG
The other ways, using an array, gives less flexibility:
char aName[] = "David"; // aName is now an array in RAM.
// You can still modify the array using the normal ways:
aName[0] = 'd';
*aName = 'd';
*(aName+0) = 'd';
strcpy(aName, "Eric"); // OK
// But not change to a larger, or a different buffer
aName = "Charlie"; // BUG: This is not possible.
Similarly, a constant array helps you even more:
const char aName[] = "David"; // aName is now a constant array.
// The compiler will prevent modification of it:
aName[0] = 'd'; // BUG
*aName = 'd'; // BUG
*(aName+0) = 'd'; // BUG
strcpy(aName, "Eric");// BUG
// And you cannot of course change it this way either:
aName = "Charlie"; // BUG: This is not possible.
The major difference between using the pointer vs array declaration is the returned value of sizeof(): sizeof(pName) is the size of a pointer, i.e. typically 4. sizeof(aName) returns the size of the array, i.e. the length of the string+1.
It matters most if the variable is declared inside a function, especially if the string is long: It occupies more of the precious stack. Thus, the array declaration is normally avoided.
It also matters when passing the variable to a macros which use sizeof(). Such macros must be supplied with the intended type.
It also matters if you want to e.g. swap the strings. Strings declared as pointers are straight-forward and requires the CPU to access less bytes, by simply moving the 4 bytes of the pointers around:
const char *pCharlie = "Charlie";
const char *pDavid = "David";
const char *pTmp;
pTmp = pCharlie;
pCharlie = pDavid;
pDavid = pTmp;
pCharlie is now "David", and pDavid is now "Charlie".
Using arrays, you must provide a temporary storage large enough for the largest string, and use strcpy(), which takes more CPU, copying byte for byte in the strings.
The last method is rarely used, since the compiler automatically calculates that David needs 6 bytes. No need to tell it what's obvious.
char aName[6] = "David";
But, it is sometimes used in cases where the array MUST be a fixed length, independent of its contents, e.g. in binary protocols or files. In that case, it can be of benefit to manually add the limit, in order to get help from the compiler, should anyone by accident add or remove a character from the string in the future.
Related
I did not get any compiler warning when I was declaring a string in the following ways:
static uint8_t test[3] = {'0','0','0'}; // (1)
static uint8_t test[3] = ""; // (2)
uint8_t test[3] = ""; // (3)
What is the difference between (2) and (3). Is this ok to do or a bad programming practice?
Also how is the string stored in memory?
Is there any chance that we write outside the size of 3?
When I do:
uint8_t test[3] = ""; //
test[0] = 0 test[1] = 0 test[2] = 0 test[3] = /0 (null character indicating the end of the string)
or do
uint8_t test[3] = "123";
test[0] = ‘1’
test[1] = ‘2’
test[2] = ‘3’
test[3] = /0 (null character indicating the end of the string)
Where is the null terminator stored ?
And what is the diffference between
test[3] = ""
test[3] = '\0'
For me this seems like I am zeroing all positions but also zeroing from position 3 as the start address and this is why I am confused.
and
uint8_t test[3] = ""
uint8_t test[3] = '\0'
I did not get any compiler warning when I was declaring a string in the following ways
You shouldn't, since it is extremely likely that uint8_t corresponds to unsigned char.
(Fictional, theoretical compilers that support uint8_t but do not resolve it as a character type would be broken, useless implementations.)
What is the difference between (2) and (3)
Possibly linkage and storage duration. Depends on where the variables are declared. This has nothing to do with uint8_t or strings as such.
Is this ok to do or a bad programming practice?
It's ok to use uint8_t for strings, but a bit strange in the generic C programming case.
There are special cases like certain kinds of embedded systems, that want to ensure that characters are always unsigned type, because they generate display symbol tables or string-based protocols etc. On such systems one would always use uint8_t or unsigned char, and never char.
Also how is the string stored in memory?
As 3 bytes, initialized to value zero (0x00). Not to be confused with the character symbol zero '0' (0x30).
Where it is stored again depends on which scope it is declared in. Note that the string literal itself is stored in different memory than the read/write array. Industry de facto standard is something along the lines of this example.
Is there any chance that we write outside the size of 3?
Yes, if you do stupid things like test[3] = '\0';. An array declared with size 3 can only access elements 0, 1 and 2, since array indexing is zero-indexed in C.
test[3] = '\0' ... Where is the null terminator stored ?
Nobody knows, it is undefined behavior. It is not guaranteed to be stored anywhere and your program might crash. Or you happen to be unlucky and your system allows you to write to that memory location.
what is the diffference between test[3] = "" and test[3] = '\0'
The former is a syntax error, the latter writes out of bounds of the array. Neither is correct.
this is why I am confused
You are confused about array declaration versus array access. They look the same but do different things. uint8_t test[3] = ""; can only be used during declaration/initialization. The [3] during declaration means an array of size 3. But [3] during array access means access item 3 in a zero-indexed array that only have items [0], [1] and [2].
The "" initializer is equivalent to {'\0'}, null termination. And then there is a rule in C stating that if an array is partially initialized, all elements that are not explicitly initialized will be initialized implicitly to value zero. In the case of "", the first item is explicitly initialized to zero because it's a null terminator, and the rest of them implicitly to zero, because that's how arrays work.
This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 3 years ago.
I am trying to change value of character array components using a pointer. But I am not able to do so. Is there a fundamental difference between declaring arrays using the two different methods i.e. char A[] and char *A?
I tried accessing arrays using A[0] and it worked. But I am not able to change values of the array components.
{
char *A = "ab";
printf("%c\n", A[0]); //Works. I am able to access A[0]
A[0] = 'c'; //Segmentation fault. I am not able to edit A[0]
printf("%c\n", A[0]);
}
Expected output:
a
c
Actual output:
a
Segmentation fault
The difference is that char A[] defines an array and char * does not.
The most important thing to remember is that arrays are not pointers.
In this declaration:
char *A = "ab";
the string literal "ab" creates an anonymous array object of type char[3] (2 plus 1 for the terminating '\0'). The declaration creates a pointer called A and initializes it to point to the initial character of that array.
The array object created by a string literal has static storage duration (meaning that it exists through the entire execution of your program) and does not allow you to modify it. (Strictly speaking an attempt to modify it has undefined behavior.) It really should be const char[3] rather than char[3], but for historical reasons it's not defined as const. You should use a pointer to const to refer to it:
const char *A = "ab";
so that the compiler will catch any attempts to modify the array.
In this declaration:
char A[] = "ab";
the string literal does the same thing, but the array object A is initialized with a copy of the contents of that array. The array A is modifiable because you didn't define it with const -- and because it's an array object you created, rather than one implicitly created by a string literal, you can modify it.
An array indexing expression, like A[0] actually requires a pointer as one if its operands (and an integer as the other). Very often that pointer will be the result of an array expression "decaying" to a pointer, but it can also be just a pointer -- as long as that pointer points to an element of an array object.
The relationship between arrays and pointers in C is complicated, and there's a lot of misinformation out there. I recommend reading section 6 of the comp.lang.c FAQ.
You can use either an array name or a pointer to refer to elements of an array object. You ran into a problem with an array object that's read-only. For example:
#include <stdio.h>
int main(void) {
char array_object[] = "ab"; /* array_object is writable */
char *ptr = array_object; /* or &array_object[0] */
printf("array_object[0] = '%c'\n", array_object[0]);
printf("ptr[0] = '%c'\n", ptr[0]);
}
Output:
array_object[0] = 'a'
ptr[0] = 'a'
String literals like "ab" are supposed to be immutable, like any other literal (you can't alter the value of a numeric literal like 1 or 3.1419, for example). Unlike numeric literals, however, string literals require some kind of storage to be materialized. Some implementations (such as the one you're using, apparently) store string literals in read-only memory, so attempting to change the contents of the literal will lead to a segfault.
The language definition leaves the behavior undefined - it may work as expected, it may crash outright, or it may do something else.
String literals are not meant to be overwritten, think of them as read-only. It is undefined behavior to overwrite the string and your computer chose to crash the program as a result. You can use an array instead to modify the string.
char A[3] = "ab";
A[0] = 'c';
Is there a fundamental difference between declaring arrays using the two different methods i.e. char A[] and char *A?
Yes, because the second one is not an array but a pointer.
The type of "ab" is char /*readonly*/ [3]. It is an array with immutable content. So when you want a pointer to that string literal, you should use a pointer to char const:
char const *foo = "ab";
That keeps you from altering the literal by accident. If you however want to use the string literal to initialize an array:
char foo[] = "ab"; // the size of the array is determined by the initializer
// here: 3 - the characters 'a', 'b' and '\0'
The elements of that array can then be modified.
Array-indexing btw is nothing more but syntactic sugar:
foo[bar]; /* is the same as */ *(foo + bar);
That's why one can do funny things like
"Hello!"[2]; /* 'l' but also */ 2["Hello!"]; // 'l'
So I want to know exactly how many ways are there to declare string. I know similar questions have been asked for several times, but I think my focus is different. As a beginner in C, I want to know which method of declaration is correct and preferable, so that I can stick to it.
We all know we can declare string in the two following ways.
char str[] = "blablabla";
char *str = "blablabla";
After reading some Q&A in stack-overflow, I was told string literal is placed in the read-only part of the memory. So in order to create modifiable string, you need to create a character array of the length of the string + 1 in the stack and copy each characters to array.
So this is what the 1st line of code doing.
However, what the 2nd line of code does is to create a character pointer and assign the pointer the address of the 1st character located in the read-only part of the memory. So this kind of declaration does not involved copying character by character.
Please let me know if I am wrong.
So far it seems quite understandable, but what really confuses me is the modifiers. For instance, some suggests
const char *str = "blablabla";
instead of
char *str = "blablabla";
because if we do something like
*(str + 1) = 'q';
It will cause undefined behavior which is horrible.
But some go even further and suggest something like
static const char *str = "blablabla";
and say this will place the string into the static memory
which will never gets modified to avoid the undefined behavior.
So which is actually the #right# way to declare a string?
Besides, I am also interested in knowing the scope when declaring string.
For example,
(You can ignore the examples, both of them are buggy as pointed out by the others)
#include <stdio.h>
char **strPtr();
int main()
{
printf("%s", *strPtr());
}
char **strPtr()
{
char str[] = "blablabla";
char *charPtr = str;
char **strPtr = &charPtr;
return strPtr;
}
will print some garbage value.
But
#include <stdio.h>
char **strPtr();
int main()
{
printf("%s", *strPtr());
}
char **strPtr()
{
char *str = "blablabla";
/*As point out by other I am returning the address of a local variable*/
/*This causes undefined behavior*/
char **strPtr = &str;
return strPtr;
}
will work perfectly fine. (NO it doesn't, it is undefined behavior.)
I think I should leave it as another question.
This question is getting too long.
A lot of your confusion comes from a common mis-understanding about C and strings: one which is explicitly stated in the title of your question. The C language does not have a native string type, so in fact there are exactly zero ways to declare a string in C.
Spend some time reading Does C Have a String type? which does a good job of explaining that.
This is evident from the fact that you can't (sensibly) do the following:
char *a, *b;
// code to point a and b at some "strings"
if (a == b)
{
// do something if strings compare equal
}
The if statement will compare the values of the pointers, not the contents of the memory they address. So, if a and b pointed to two different areas of memory, each containing identical data, the comparison a == b would fail. The only time the comparison would evaluate as "true" (i.e. something other than zero), would be if a and b held the same address (i.e. pointed to the same location in memory).
What C has is a convention, and some syntactic sugar to make life easier.
The convention is that a "string" is represented as a sequence of char terminated with the value zero (usually referred to as NUL and represented by the special character escape sequence '\0'). This convention comes from the API of the original standard library (back in the 70's) which provides a set of string primitives such as strcpy(). These primitives were so fundamental to doing anything truly useful in the language that life was made easier for programmers by adding syntactic sugar (this is all before the language escaped from the lab).
The syntactic sugar is the existence of "string literals": no more, and no less. In source code, any sequence of ASCII characters, enclosed in double quotes, is interpreted as a string literal and the compiler produces a copy (in "read-only" memory) of the characters plus a terminating NUL byte to conform to the convention. Modern compilers detect duplicated literals and only produce a single copy - but it's not a requirement of the standard last time I looked. Thus this:
assert("abc" == "abc");
may or may not raise an assertion - which reinforces the statement that C does not have a native string type. (For that matter, neither does C++ - it has a String class!)
With that out of the way, how do you use string literals to initialize a variable?
The first (and most common) form you will see is this
char *p = "ABC";
Here, the compiler sets aside 4 bytes (assuming sizeof(char) ==1) of memory in a "read only" section of the program and initializes it with [0x41, 0x42, 0x43, 0x00]. It then initializes p with the address of that array. You should note that there is some const casting going on here as the underlying type of a string literal is const char * const (a constant pointer to a constant character). Which is why you would normally be advised to write this as:
const char *p = "ABC";
Which is a "pointer to a constant char" - another way of saying "pointer to read only memory".
The next two forms use string literals to initialize arrays
char p1[] = "ABC";
char p2[3] = "ABC";
Note that there is a critical difference between the two. the first line creates a 4 byte array. The second creates a 3 bytes array.
In the first case, as before, the compiler creates a 4 byte constant array containing [0x41, 0x42, 0x43, 0x00]. Note that it adds the trailing NUL to form a "C String". It then reserves four bytes of RAM (on the stack for a local variable, or in "static" memory for variables at file scope) and inserts code to initialize it at run time by copying the "read only" array into the allocated RAM. You are now free to modify elements of p1 at will.
In the second case, the compiler creates a 3 byte constant array containing [0x41, 0x42, 0x43]. Note that there is no trailing NUL. It then reserves 3 bytes of RAM (on the stack for a local variable, or in "static" memory for variables at file scope) and inserts code to initialize it at run time by copying the "read only" array into the allocated RAM. You are again now free to modify elements of p2 at will.
The difference in sizes of the two arrays p1 and p2 is critical. The following code (if you ran it) would demonstrate it.
char p1[] = "ABC";
char p2[3] = "ABC";
printf ("p1 = %s\n", p1); // Will print out "p1 = ABC"
printf ("p2 = %s\n", p2); // Will print out "p2 = ABC!##$%^&*"
The output of the second printf is unpredictable, and could theoretically result in your code crashing. It tends to seem to work, simply because so much of RAM is filled with zeroes that eventually printf finds a terminating NUL.
Hope this helps.
I read that:
char a[] = "string";
is a: "string"
whereas
char *ptr = "string"
is ptr: [__] ---> "string"
I am little confused. One thing I know is that pointers always store the address. In case of character pointer what address does it store? What does this block represent (block which I made pointing to string). Is it the starting address of the "string".
And in case of array? How can I clearly differentiate between char pointer and char array?
Diagrams may help.
char *ptr = "string";
+-------+ +----------------------------+
| ptr |--------->| s | t | r | i | n | g | \0 |
+-------+ +----------------------------+
char a[] = "string";
+----------------------------+
| s | t | r | i | n | g | \0 |
+----------------------------+
Here, ptr is a variable that holds a pointer to some (constant) data. You can subsequently change the memory address that it points at by assigning a new value to ptr, such as ptr = "alternative"; — but you cannot legitimately change the contents of the array holding "string" (it is officially readonly or const, and trying to modify it may well crash your program, or otherwise break things unexpectedly).
By contrast, a is the constant address of the first byte of the 7 bytes of data that is initialized with the value "string". I've not shown any storage for the address because, unlike a pointer variable, there isn't a piece of changeable storage that holds the address. You cannot change the memory address that a points to; it always points to the same space. But you can change the contents of the array (for example, strcpy(a, "select");).
When you call a function, the difference disappears:
if (strcmp(ptr, a) == 0)
…string is equal to string…
The strcmp() function takes two pointers to constant char data (so it doesn't modify what it is given to scrutinize), and both ptr and a are passed as pointer values. There's a strong case for saying that only pointers are passed to functions — never arrays — even if the function is written using array notation.
Nevertheless, and this is crucial, arrays (outside of paramter lists) are not pointers. Amongst other reasons for asserting that:
sizeof(a) == 7
sizeof(ptr) == 8 (for 64-bit) or sizeof(ptr) == 4 (32-bit).
In case of character pointer what address does it store? What does this block represent (block which I made pointing to string). Is it the starting address of the "string".
This blocks represents a WORD or DWORD (achitecture dependant), the content of this block is a memory address, a random location defined at compile time. That memory address is the address of first character of the string.
In practice, the difference is how much stack memory it uses.
For example when programming for microcontrollers where very little memory for the stack is allocated, makes a big difference.
char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK
char *b = "string"; // the compiler puts just the pointer onto STACK
// and {'s','t','r','i','n','g',0} in static memory area.
Maybe this will help you understand.
assert(a[0] == 's'); // no error.
assert(b[0] == 's'); // no error.
assert(*b == 's'); // no error.
b++; // increment the memory address, so points to 't'
assert(*b == 's'); // assertion failed
assert(*b == 't'); // no error.
char a[] = "string"; initializes the value of the array of chars called a with the value string. And the size of a.
char *a = "string"; creates an unnamed static array of chars somewhere in memory and return the address of the first element of this unnamed array to a.
In the first one, a stores the address of the first element of the array. So when we index something like a[4], this means 'take' the 4th element after the begin of the object named a.
In the second, a[4] means 'take' the 4th element after the object that a points to.
And for your last question:
A char array is a 'block' of contiguous elements of type char. A char pointer is a reference to an element of the type char.
Due to pointer arithmetics, a pointer can be used to simulate (and access) an array.
Maybe those 3 links help make the difference more clear:
http://c-faq.com/decl/strlitinit.html
http://c-faq.com/aryptr/aryptr2.html
http://c-faq.com/aryptr/aryptrequiv.html
You may find it useful to think of:
char * a = "string";
as the same as:
char SomeHiddenNameYouWillNeverKnowOrSee[] = "string"; /* may be in ReadOnly memory! */
char * a = &SomeHiddenNameYouWillNeverKnowOrSee[0];
Did you ever tried to open some executabe file with a text editor ? It appears merely as garbage, but in the middle of the garbage you can see some readable strings. These are all the litteral strings defined in you program.
printf("my literal text");
char * c = "another literal text"; // should be const char *, see below
If your program contains the above code you may be able to find my literal textand another literal text in program's binary (actually it depends on the details of the binary format, but it often works). If you are Linux/Unix user you can also use the strings command for that.
By the way, if you write the above code, C++ compilers will emit some warning (g++ say: warning: deprecated conversion from string constant to ‘char*’ because such strings are not of type char * but const char [] (const char array) which decay to const char * when assigned to a pointer.
This also is the case with C compilers, but the above error is so very common that this warning is usually disabled. gcc does not even include in -Wall, you have to explicitely enable it through -Wwrite-strings. The warning is warning: initialization discards ‘const’ qualifier from pointer target type.
It merely reminds that you are theoretically not allowed to change the literal texts through pointers.
The executable may loads such strings in a read only part of Data segment memory. If you try to change the content of string it can raise a memory error. Also the compiler is allowed to optimise literal text storage by merging identical strings for instance. The pointer just contains the address in (read only) memory where the literal strings will be loaded.
On the other hand
char c[] = "string"; is mere syntaxic sugar for char c[7] = {'s', 't', 'r', 'i', 'n', 'g', 0}; If you do sizeof(c) in your code it will be 7 bytes (the size of the array, not the size of a pointer). This is an array on stack with an initialiser. Internally the compiler can do wathever it likes to initialize the array. It can be characters constants loaded one by one in the array, or it can involved a memcpy of some hiden string literal. The thing is that you have no way to tell the difference from your program and find out where the data comes from. Only the result matters.
By the way a thing that is slightly confusing is that if you define some function parameter of the type char c[], then it won't be an array but an alternative syntax for char * c.
In your example, ptr contains the address of the first char in the string.
As for the difference between a char array and a string, in C terms there is no difference other than the fact that by convention what we call "string" is a char array where the final char is a NULL, to terminate the string.
i.e. even if we have an array of char with 256 potential elements, if the first (0th) char is null (0) then the length of the string is 0.
Consider a variable str which is a char array of 5 chars, containing the string 'foo'.
*ptr => str[0] 'f'
str[1] 'o'
str[2] 'o'
str[3] \0
str[4] ..
A char *ptr to this array would reference the first element (index = 0) and the 4th element (index = 3) would be null, marking the end of the 'string'. The 5th element (index = 4) will be ignored by string handling routines which respect the null terminator.
If you are asking what a contains in each case then:
char a[] = "string";
// a is a pointer.
// It contains the address of the first element of the array.
char *a = "string";
// Once again a is a pointer containing address of first element.
As rnrneverdies has explained in his answer, the difference is in where the elements are stored.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Question about pointers and strings in C
I'm reading about the strings in C and I'm confused. I can "declare" strings in two ways:
char *str = "This is string";
char str2[20] = "This is string";
What is the difference between the two declarations? When would char str2[20] be preferred over char *str?
In C, strings are represented as sequences of chars, with a NULL character (aka 0, '\0'). They are stored in memory and you work with a way of referencing it. You have identified the two ways of referencing it, a char *, which is a pointer to a sequence of chars and an array, which is an immediate string of chars as an actual variable. Be aware that the string "abc" is 4 bytes long as there is an additional NULL character to represent the end of the string.
In addition to this, you are actually assigning strings in the example, which also involves the strings to given at compile-time.
So two questions. First is about how you represent strings (char * vs char[]) the second is about compile-time strings.
To come to your examples:
The first one creates a constant string in the text of the program and a pointer to it. Depending on the compiler it may be stored anywhere. It is the equivalent of mallocing a string and storing a pointer to it, except you must not change the contents of the memory. It is a char *, so you can change the pointer to point to somewhere else, like another malloced string or to the start of an array that you defined in example 2.
The second creates a char array (which a way of representing a string). The array is stored and allocated on the stack for the duration of the function, and you may change the contents. Because it is not a pointer, you cannot change it to point to a different string.
char *str = "This is string";
Puts the string in the constant data section (also known as .rdata) of the program.This data can't be modified.
char str2[20] = "This is string";
In this type of declaration data is preferably stored in the stack area of the program, if declared inside the function scope and in data section if declared in global scope.This data can be modified.
So if you have a necessity to modify data then use the second approach.
C has no strings. All there is is char arrays. And arrays in C are just pointers to the first element.
The easiest way of doing it is in fact your first variant. Not specifying an explicit length of the array for literals will save you from accidentally doing something like
char[3] = "abc";
C strings are constant in memory, so:
char *str = "This is string";
Stores "This is string" in memory and it is not mutable, you can only assign another address to str.
However
char str2[20] = "This si string";
is a shorthand of
char String2[20]={'T','h','i','s',' ','s','i',' ','s','t','r','i','n','g','\0'};
which does not stores a string in memory, stores independent bytes.
If you want to use constant strings like messages, then use first line.
If you want to use and manipulate strings like in a word processor then use second.
Regards
char *str = "This is string"; - This will keep the string in text segment as a read only data and it will store the address in the local pointer variable str.
str[0] = 'a'; //This will leads to crash, because strings are in read only segment.
printf("%d",sizeof(str)); //This will print 4(in 32bit m/c) or 8(in 64 bit m/c)
char str2[20] = "This is string"; - This will keep the string as character array in local stack.
str2[0] = 'a'; //This will change the first character to a
printf("%d",sizeof(str2)); //This will print 20