How to declare strings in C [duplicate] - c

This question already has answers here:
Memory Allocation char* and char[]
(3 answers)
Closed 3 years ago.
Can anyone explain me what is a difference between these lines of code
char *p = "String";
char p2[] = "String";
char p3[7] = "String";
In what case should I use each of the above ?

This link should satisfy your curiosity.
Basically (forgetting your third example which is bad), the different between 1 and 2 is that 1 allocates space for a pointer to the array.
But in the code, you can manipulate them as pointers all the same -- only thing, you cannot reallocate the second.

Strings in C are represented as arrays of characters.
char *p = "String";
You are declaring a pointer that points to a string stored some where in your program (modifying this string is undefined behavior) according to the C programming language 2 ed.
char p2[] = "String";
You are declaring an array of char initialized with the string "String" leaving to the compiler the job to count the size of the array.
char p3[5] = "String";
You are declaring an array of size 5 and initializing it with "String". This is an error be cause "String" don't fit in 5 elements.
char p3[7] = "String"; is the correct declaration ('\0' is the terminating character in c strings).
http://c-faq.com/~scs/cclass/notes/sx8.html

You shouldn't use the third one because its wrong. "String" takes 7 bytes, not 5.
The first one is a pointer (can be reassigned to a different address), the other two are declared as arrays, and cannot be reassigned to different memory locations (but their content may change, use const to avoid that).

char *p = "String"; means pointer to a string type variable.
char p3[5] = "String"; means you are pre-defining the size of the array to consist of no more than 5 elements. Note that,for strings the null "\0" is also considered as an element.So,this statement would give an error since the number of elements is 7 so it should be:
char p3[7]= "String";

Related

Why pointers can't be used to index arrays? [duplicate]

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'

Queries on declaring & initialising string and also string memory region [duplicate]

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)
What is the difference between char s[] and char *s?
(14 answers)
Closed 3 years ago.
My question comes in three part.
char str[] = "hello!";
char *str1 = "heello!";
puts(str);
str1[1] = 1
puts(str1);
printf("%s\n", str1);
printf("%p\n", str1);
Ouput of code:
hello!
h1ello!
heello!
0x10735ef9b
1) I understand that when you're declaring a char * type, you're declaring a pointer that points to char type. And usually for pointer, since it contains the address of the variable its pointing to, when you print the pointer itself, you'll get the address stored in the pointer and only when you dereference the pointer, then you'll get the content stored in the variable the pointer is pointing to.
However for a char * type, why is it that it doesn't function like a regular pointer? You can print the content of the variable which the 'char *' pointer is pointing to without dereferencing it and also use it like a string variable(rather than a pointer) by changing the value of the str1[1] as shown above.
2) I was taught that you shouldn't declare a pointer variable as such in the topic of pointer:
char *str1 = "heello!";
because the pointer variable would be pointing to whatever address happens to be in the memory at that time, thus running a risk of changing the value in a memory location that you don't mean to and resulting in segfault.
Hence you should do the following:
char *str1;
char c;
str1 = &c;
*addr = "hello!"
By doing the above, you'll make sure that your pointer is pointing to the right location before dereferencing and writing to the location.
However in the notes on string, it says to declare and initialise as such:
char *str1 = "heello!";
I'm quite confused as to what I should follow now when declaring a char * pointer. Please help.
3) It says in my notes that the location of string is stored in a read only region of the memory called the text region.
Hence doing this:
char *str1 = "hello!";
str[1] = '.';
Will crash your program.
But when you do this:
char str2[7] = "hello!";
str2[1] = '.';
This is okay and will successfully change the second element in the string from 'e' to '.'
The explanation to this was that str1 points to a read only region in the memory, while str2 contains a copy of the string on the stack.
I do not understand how the above 2 different ways of declaring the string variable will make such a big difference when executing the code. Please help.
Thank you!
String literals like "heello!" are really read-only arrays of characters (including the string null-terminator).
With
char *str1 = "heello!";
you make str1 point to the first character of such an array.
And when you do str1[1] = 1 you attempt to modify the read-only array, which is forbidden and leads to undefined behavior (which can but doesn't have to lead to crashes).
That's why you either should use your own arrays for strings, or use const char * to point to literal strings.

Confusion in basic concept of pointers and strings [duplicate]

This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 9 years ago.
In my GCC 32-bit compiler, the following code gives the output
char *str1="United";
printf("%s",str1);
output:
United
then should I consider char *str1="United"; the same as char str1[]="United"?
The two are not the same: char *str1="United" gives you a pointer to a literal string, which must not be modified (else it's undefined behavior). The type of a literal string should really be const but it's non-const for historical reasons. On the other hand, char str1[]="United" gives you a modifiable local string.
char* str = "United"; is read-only. You wouldn't be able to reach inside the string and change parts of it:
*str = 'A';
Will most likely give you a segmentation fault.
On the other hand char str1[] = "United"; is an array and so it can be modified as long as you don't exceed the space allocated for it (arrays cannot be resized). For example this is perfectly legal:
char str[] = "United";
str[0] = 'A';
printf("%s\n", str);
This will print Anited.
See the comp.lang.c.faq, question 1.32. It basically boils down to the fact that declaring the string in array form (char str[] = "foo") is identical to char str[] = {'f','o','o'}, which is identical to char str[] = {102, 111, 111}; that is, it is a normal array on the stack. But when you use a string literal in any other context it becomes "an unnamed, static array of characters, [which] may be stored in read-only memory, and which therefore cannot necessarily be modified." (And trying to modify it results in undefined behavior wherever it happens to be stored, so don't).

Difference between char *str = "…" and char str[N] = "…"? [duplicate]

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

once defined ,string cannot be initialized to other characters? [duplicate]

This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
C - why is strcpy() necessary
(4 answers)
Closed 8 years ago.
Using pointers string can be initialized to other characters but when once string has been defined it cannot be initialized to other characters.What is the reason behind it??
int main()
{
char str1[]="hello";
char *p="hello";
str1="bye";/*error*/
p="bye";/*works*/
}
You've defined str1 as an array, and arrays aren't assignable.
You can, however, copy other data into the array, for example:
char str1[] = "hello";
strcpy(str1, "bye");
Arrays are arrays and pointers are pointers. Defining arrays gives the pointer to the allocated array, that is a constant pointer to the location where the array space hass been reserved. That is a concrete address in the lifo stack. So, str1 is a constant pointer value and you cannot change it. You cannot set the value of the address of a different constant string.
Defining pointers, as char*p, gives you a variable value of an address. And so, you can change de value of the variable p.
To change the characters in an array such as what you are doing you have to use a function such as strcpy or do it index by index.
str1[0] = 'p';
will print out pello
What you are trying to do is not supported by the C language.

Resources