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
Related
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
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 2 years ago.
I have a struct defined similar to the following:
struct csv_headers {
char field1[256];
char field2[256];
};
And then later in my code I have:
struct csv_headers fields;
strcpy(fields.field1, str_ary[0]);
strcpy(fields.field2, str_ary[1]);
Where str_ary[n] is some string.
Does this cause undefined behaviour the same way the following code would?
char str[] = "some text";
strcpy(str, "text");
Since strcpy should not be used for string literals?
If so, what is the accepted way to copy a string into a string declared inside a struct? My code example above compiles with no warnings using -Wextra (assuming I typed it correctly - I don't have the code in front of me right now).
I am aware of the potential dangers of using strcpy and don't wish to discuss that here, that is for illustrative purposes only. I just want to know the accepted way of copying a string into a struct containing strings.
Does this cause undefined behaviour the same way the following code would?
char str[] = "some text";
strcpy(str, "text");
Since strcpy should not be used for string literals?
str isn’t a string literal, it’s a char[10] (initialised by copying data from a string literal1), and it’s a valid target for strcpy. This code does not cause undefined behaviour; it’s well-defined and valid.
Likewise, fields.field1 and fields.field2 in your example are regular char[]s. That they’re members of a struct isn’t important in this context.
However, be sure that the source is valid: str_ary[0] looks fishy, unless str_ary is an array of zero-terminated strings, i.e. something like char[][].
1 The initialisation of a string array from a string literal happens as if by strcpy, i.e. it’s almost exactly the same as writing
char str[sizeof("some text")];
strcpy(str, "some text");
In fact, compilers could (and at least in some cases do) generate the same code for this initialisation as for the direct assignment. By contrast, char *str = "some text"; doesn’t perform copying, and here str is a pointer to a string literal, and therefore read-only, and not a valid target for strcpy.
Does this cause undefined behaviour the same way the following code would?
Well, your snippet does not cause problems.
char str1[] = "foo"; // str1 is a regular array initialized to "foo"
char *str2 = "bar" // str2 is a pointer, pointing to a string literal
strcpy(str1, "FOO"); // Ok
strcpy(str2, "BAR"); // Undefined behavior
As long as the string fits in the target space, even
char str[] = "some text";
strcpy(str, "text");
is well-defined.
char field1[256]; declares an array with room for 256 characters. This allows you to store a null-terminated string of up to 255 characters (the array size, minus one for the null terminator).
char str[256] = "some text"; additionally initializes the array to contain the string "some text". You can still copy a string of up to 255 characters into the array, since that's how much room there is.
char str[] = "some text"; is exactly identical to char str[10] = "some text";. With the empty brackets, str is still an array of characters. What the empty brackets mean is that the size of the array (what would normally go inside the brackets) is determined automatically. There is no other difference compared with brackets with a size in it. For an array of characters, the size is the length of the string plus one for the null terminator.
In all cases involving an array, the string used to initialize the array (if there is one) is stored in the array itself. It isn't accessible in any other way, and if you change the array, the string that was used to initialize it is not present in memory anymore (at least in the sense that there's no way to find it — there's no guarantee that it won't be present in a memory dump, but you have no way to access it from your program).
The critical difference is not between char str[10] and char str[], but between char str[…] and char *p. With a * instead of brackets, char *p declares a pointer, not an array.
char *p = "some text";
does two things. One thing is that it arranges for a string literal "some text" to be stored somewhere that's accessible for the whole duration of the program. Another thing is that it declares a variable p that points to this string literal. You cannot modify the memory where "some text" is stored (in practice, on many platforms, it's in read-only memory). On the other hand, you can make something else point to that memory, and you can change p to point to something else.
char *p = "some text";
char *q;
puts(p); // prints "some text"
q = p;
p = "hello";
puts(q); // prints "some text"
puts(p); '// prints "hello"
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 6 years ago.
#include <stdio.h>
int main(){
char *ch = "Hello, World";//character pointer pointing to a string without declaration.
printf("%s", ch);//printing the string without <i>dereferencing</i> it.
}
I saw an example in a book, with code as given above. I don't understand how a character pointer points to a string without declaring a string first.Also there is no dereference operator used to print the string.
As stated very well by #tryurbest, Why it works with pointers:
When you say char * ch in C, you are allocating a pointer in the memory. When you write char *ch = "Hello, World";, you are creating a string literal in memory and making the pointer point to it. When you create another string literal "new string" and assign it to ch, all you are doing is changing where the pointer points.
On the other hand, for added information, Why it doesn't work with arrays:
When you say char ch1 [] = "Hello, World", you are creating a string literal and putting it in the array during its definition. It is ok to not give a size, as the array calculates it and appends a '\0' to it. You cannot reassign anything to that array without resizing it.
Hope this helps to clarify some things.
"Hello, World" is a string literal or read only memory store in data block. A variable ch is pointer to char, which is initialized with the location of the first character.
That's simply how printf works with a const char* argument. (Your pointer actually points to const data.)
Starting at the memory location denoted by the pointer, it prints character by character until a NUL terminator is reached.
The C standard library string functions all work in this way. Simply put it's how the language models strings.
A few questions regarding C strings:
both char* and char[] are pointers?
I've learned about pointers and I can tell that char* is a pointer, but why is it automatically a string and not just a char pointer that points to 1 char; why can it hold strings?
Why, unlike other pointers, when you assign a new value to the char* pointer you are actually allocating new space in memory to store the new value and, unlike other pointers, you just replace the value stored in the memory address the pointer is pointing at?
A pointer is not a string.
A string is a constant object having type array of char and, also, it has the property that the last element of the array is the null character '\0' which, in turn, is an int value (converted to char type) having the integer value 0.
char* is a pointer, but char[] is not. The type char[] is not a "real" type, but an incomplete type. The C language is specified in such a way that, in the moment that you define a concrete variable (object) having array of char type, the size of the array is well determined in some way or another. Thus, none variable has type char[] because this is not a type (for a given object).
However, automatically every object having type array of N objects of type char is promoted to char *, that is, a pointer to char pointing to the initial object of the array.
On the other hand, this promotion is not always performed. For example, the operator sizeof() will give different results for char* than for an array of N chars. In the former case, the size of a pointer to char is given (which is in general the same amount for every pointer...), and in the last case gives you the value N, that is, the size of the array.
The behaviour is differente when you declare function arguments as char* and char[]. Since the function cannot know the size of the array, you can think of both declarations as equivalent.
Actually, you are right here: char * is a pointer to just 1 character object. However, it can be used to access strings, as I will explain you now: In the paragraph 1. I showed you that the strings are considered objects in memory having type array of N chars for some N. This value N is big enough to allow an ending null character (as all "string" is supposed to be in C).
So, what's the deal here?
The key point to understand this issues is the concept of object (in memory).
When you have a string or, more generally, an array of char, this means that you have figured out some manner to hold an array object in memory.
This object determines a portion of RAM memory that you can access safely, because C has assigned enough memory for it.
Thus, when you point to the first byte of this object with a char* variable, actually you have guaranteed access to all the adjacent elements to the "right" of that memory place, because those places are well defined by C as having the bytes of the array above.
Briefly: the adjacent (to the right) bytes of the byte pointed by a char* variable can be accessed, they are valid places to access, so the pointer can be "iterated" to walk through these bytes, up to the end of the string, without "risks", since all the bytes in an array are contiguous well defined positions in memory.
This is a complicated question, but it reveals that you are not understanding the relationship between pointers, arrays, and string literals in C.
A pointer is just a variable pointing to a position in memory.
A pòinter to char points to just 1 object having type char.
If the adjacent bytes of the pointed position correspond to an array of chars, they will be accessible by the pointer, so the pointer can "walk on" the memory bytes occupied by the array object.
A string literal is considered as an array of char object, which implictely add an ending byte with value 0 (the null character).
In any case, an array of T object has a well defined "size".
A string literal has an additional property: it's a constant object.
Try to fit and gather these concepts in your mind to figure out what's going on.
And ask me for clarification.
ADDITIONAL REMARKS:
Consider the following piece of code:
#include <stdio.h>
int main(void)
{
char *s1 = "not modifiable";
char s2[] = "modifiable";
printf("%s ---- %s\n\n", s1, s2);
printf("Size of array s2: %d\n\n", (int)sizeof(s2));
s2[1] = '0', s2[3] = s2[5] = '1', s2[4] = '7',
s2[6] = '4', s2[7] = '8', s2[9] = '3';
printf("New value of s2: %s\n\n",s2);
//s1[0] = 'X'; // Attempting to modify s1
}
In the definition and initialization of s1 we have the string literal "not modifiable", which has constant content and constant address. Its address is assigned to the pointer s1 as initialization.
Any attempt to modify the bytes of the string will give some kind of error, because the array content is read-only.
In the definition and initialization of s2, we have the string literal "modifiable", which has, again, constant content and constant address. However, what happens now is that, as part of the initialization, the content of the string is copied to the array of char s2. The size of the array s2 is not specified (the declaration char s2[] gives an incomplete type), but after initialization the size of the array is well determined and defined as the exact size of the copied string (plus 1 character used to hold the null character, or end-of-string mark).
So, the string literal "modifiable" is used to initialize the bytes of the array s2, which is modifiable.
The right manner to do that is by changing a character at the time.
For more handy ways of modifying and assigning strings, it has to be used the standard header <string.h>.
char *s is a pointer, char s[] is an array of characters. Ex.
char *s = "hello";
char c[] = "world";
s = c; //Legal
c = address of some other string //Illegal
char *s is not a string; it points to an address. Ex
char c[] = "hello";
char *s = &c[3];
Assigning a pointer is not creating memory; you are pointing to memory. Ex.
char *s = "hello";
In this example when you type "hello" you are creating special memory to hold the string "hello" but that has nothing to do with the pointer, the pointer simply points to that spot.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Do these statements about pointers have the same effect?
All this time I thought that whenever I need to copy a string(either literal or in a variable) I need to use strcpy(). However I recently found out this:
char a[]="test";
and this
char *a="test";
From what I understand the second type is unsafe and will print garbage in some cases. Is that correct? What made me even more curious is why the following doesn't work:
char a[5];
a="test";
or this
char a[];
a="test";
but this works however
char *a;
a="test";
I would be greatful if someone could clear up things a bit.
char a[]="test";
This declares and initializes an array of size 5 with the contents of "test".
char *a="test";
This declares and initializes a pointer to the literal "test". Attempting to modify a literal through a is undefined behavior (and probably results in the garbage you are seeing). It's not unsafe, it just can't be modified since literals are immutable.
char a[5];
a="test";
This fails even when both a and "test" have the exact same type, just as any other attempt to copy arrays thorugh assignment.
char a[];
a="test";
This declares an array of unknown size. The declaration should be completed before being used.
char *a;
a="test";
This works just fine since "test" decays to a pointer to the literal's first element. Attempting to modify its contents is still undefined behavior.
Let's examine case by case:
char a[]="test";
This tells the compiler to allocate 5 bytes on the stack, put 't' 'e' 's' 't' and '\0' on it. Then the variable a points to where 't' was written and you have a pointer pointing to a valid location with 5 available spaces. (That is if you view a as a pointer. In truth, the compiler still treats a as a single custom type that consists of 5 chars. In an extreme case, you can imagine it something like struct { char a, b, c, d, e; } a;)
char *a="test";
"test" (which like I said is basically 't' 'e' 's' 't' and '\0') is stored somewhere in your program, say a "literal's area", and a is pointing to it. That area is not yours to modify but only to read. a by itself doesn't have any specific memory (I am not talking about the 4/8 bytes of pointer value).
char a[5];
a = "test";
You are telling the compiler to copy the contents of one string over to another one. This is not a simple operation. In the case of char a[] = "test"; it was rather simple because it was just 5 pushes on the stack. In this case however it is a loop that needs to copy 1 by 1.
Defining char a[];, well I don't think that's even possible, is it? You are asking for a to be an array of a size that would be determined when initialized. When there is no initialization, it's just doesn't make sense.
char *a;
a = "test";
You are defining a as a pointer to arrays of char. When you assign it to "test", a just points to it, it doesn't have any specific memory for it though, exactly like the case of char *a = "test";
Like I said, assigning arrays (whether null-terminated arrays of char (string) or any other array) is a non-trivial task that the compiler doesn't do for you, that is why you have functions for it.
Do not confuse assignment and initialisation in C, they are different.
In C a string is not a data type, it is a convention, utilising an array and a nul terminator. Like any array, when you assign it, it's name resolves as a mere pointer. You can assign a pointer, but that is not the same as assigning a string.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Why is:
char *ptr = "Hello!"
different than:
char ptr[] = "Hello!"
Specifically, I don't see why you can use (*ptr)++ to change the value of 'H' in the array, but not the pointer.
Thanks!
You can (in general) use the expression (*ptr)++ to change the value that ptr points to when ptr is a pointer and not an array (ie., if ptr is declared as char* ptr).
However, in your first example:
char *ptr = "Hello!"
ptr is pointing to a literal string, and literal strings are not permitted to be modified (they may actually be stored in memory area which are not writable, such as ROM or memory pages marked as read-only).
In your second example,
char ptr[] = "Hello!";
The array is declared and the initialization actually copies the data in the string literal into the allocated array memory. That array memory is modifiable, so (*ptr)++ works.
Note: for your second declaration, the ptr identifier itself is an array identifier, not a pointer and is not an 'lvalue' so it can't be modified (even though it converts readily to a pointer in most situations). For example, the expression ++ptr would be invalid. I think this is the point that some other answers are trying to make.
When pointing to a string literal, you should not declare the chars to be modifiable, and some compilers will warn you for this:
char *ptr = "Hello!" /* WRONG, missing const! */
The reason is as noted by others that string literals may be stored in an immutable part of the program's memory.
The correct "annotation" for you is to make sure you have a pointer to constant char:
const char *ptr = "Hello!"
And now you see directly that you can't modify the text stored at the pointer.
Arrays automatically allocate space and they can't be relocated or resized while pointers are explicitly assigned to point to allocated space and can be relocated.
Array names are read only!
If You use a string literal "Hello!", the literal itself becomes an array of 7 characters and gets stored somewhere in a data memory. That memory may be read only.
The statement
char *ptr = "Hello!";
defines a pointer to char and initializes it, by storing the address of the beginning of the literal (that array of 7 characters mentioned earlier) in it. Changing contents of the memory pointed to by ptr is illegal.
The statement
char ptr[] = "Hello!";
defines a char array (char ptr[7]) and initializes it, by copying characters from the literal to the array. The array can be modified.
in C strings are arrays of characters.
A pointer is a variable that contains the memory location of another variable.
An array is a set of ordered data items.
when you put (*ptr)++ you are getting Segmentation Fault with the pointer.
Maybe you are adding 1 to the whole string (with the pointer), instead of adding 1 to the first character of the variable (with the array).