i try to print simple c* string like this :
char *cc = "HEllo";
for (char* inputPtr = cc; inputPtr[0]; inputPtr++) {
char c = inputPtr[0]++;
printf("%s",c);
}
but im getting :
Access violation writing location 0x00CFB310.
on :
char c = inputPtr[0]++;
what is wrong here ?
It looks like you are experimenting with inputPtr[0] as a substitution for *inputPtr. In many contexts, the two expressions produce the same result.
However, expression inputPtr[0]++ is not the same as *inputPtr++, because [0] has higher precedence than *, but it has the same precedence as suffix ++. Operators within this precedence level are applied left-to-right, so the first expression post-increments inputPtr[0], a character inside a character literal. This is undefined behavior, hence you see a crash.
If you replace inputPtr[0]++ with *inputPtr++ and remove inputPtr++ from loop header, your code is going to work fine:
for (char* inputPtr = cc; inputPtr[0]; ) {
char c = *inputPtr++;
printf("%c", c); // Replace %s with %c to print one character
}
inputPtr is pointing at "HEllo", which is a string literal.
Modifying string literal isn't allowed and trying to do so invokes undefined behavior.
inputPtr[0]++ is trying to modify string literal. If data of string literal is located in read-only locations, it may lead to Segmentation Fault.
String literals in C are read only, attempting to modify the characters in string literals leads to undefined behavior.
Any with inputPtr[0] you do modify the string since you increment the character inputPtr[0].
This is the reason you should always use const char * when pointing to string literals.
If you want to modify the contents of the string you have to create an array:
char cc[] = "HEllo";
As the others have written, you can't modify a string literal. Change your declaration to char cc[] = "HEllo"; and see what happens. The suggested declaration declares a string buffer that is modifiable.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does this Seg Fault?
I receive a segmentation fault when using ++ operator on a char *
#include<stdio.h>
int main()
{
char *s = "hello";
printf("%c ", ++(*s));
return 0;
}
But if I do the following:
#include<stdio.h>
int main()
{
char *s = "hello";
char c = *s;
printf("%c ", ++c);
return 0;
}
Then the code compiles perfectly, what is the problem with the above code?
The first code snippet is attempting to modify a character in a string literal as:
++(*s)
is attempting to increment the first character in s. String literals are (commonly) read-only and an attempt to modify will cause the segmentation fault (the C standard states If the program attempts to modify such an array, the behavior is undefined.).
The second snippet is modifying a char variable, which is not read-only as after:
char c = *s;
c is a copy of the first character in s and c can be safely incremented.
In the first case you modify a constant literal, and in the second you modify a variable.
This code:
printf("%c ", ++(*s));
tries to modify a string literal through a pointer to one of its characters. Modifying string literals is undefined behavior - the quite likely outcome is that string literals are often stored in read-only memory, so it's technically illegal to modify them and that's why it manifests itself as segmentation fault on your system.
char *s = "hello";
This implies that 's' is a const string.
If you need a non-const string, you should allocate it explicitly from heap.
You are trying to change a string literal in the first case which is not allowed. In the second case you create a new char from the first character of the string literal. You modify the copy of that character and that is why the second case works.
Your code does not have write permission for the segment where the string literal is stored.
The program is:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *a="abc",*ptr;
ptr=a;
ptr++;
*ptr='k';
printf("%c",*ptr);
return 0;
}
The problem is in the
*ptr='k';
line, when I remove it program works normally. But I can't figure out the reason.
The problem is because you are trying to change the string literal "abc" with:
char *a="abc",*ptr;
ptr=a; // ptr points to the 'a'.
ptr++; // now it points to the 'b'.
*ptr='k'; // now you try to change the 'b' to a 'k'.
That's undefined behaviour. The standard explicitly states that you are not permitted to change string literals as per section 6.4.5 String literals of C99:
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
It will work if you replace:
char *a="abc",*ptr;
with:
char a[]="abc",*ptr;
since that copies the string literal to a place that's safe to modify.
Because "abc" is a constant string literal. Then you point ptr to it and try to modify it which is undefined behaviour. Typically string literals are put in a memory section which gets mapped as read-only - hence the access violation.
See also this question: String literals: Where do they go?
The reason is that your string "abc" lives in a read-only area of memory. It gets put there by the linker. You try to change it in your program, and all bets are off.
This:
char *a="abc";
is really:
const char *a="abc";
You can't modify ptr, which points to the same address as a.
I am working on Microsoft Visual Studio environment. I came across a strange behavior
char *src ="123";
char *des ="abc";
printf("\nThe src string is %c", src[0]);
printf("\tThe dest string is %c",dest[0]);
des[0] = src[0];
printf("\nThe src string is %c", src[0]);
printf("\tThe dest string is %c",dest[0]);
The result is:
1 a
1 a
That means the des[0] is not being initialized. As src is pointing to the first element of the string. I guess by rules this should work.
This is undefined behavior:
des[0] = src[0];
Try this instead:
char des[] ="abc";
Since src and des are initialized with string literals, their type should actually be const char *, not char *; like this:
const char * src ="123";
const char * des ="abc";
There was never memory allocated for either of them, they just point to the predefined constants. Therefore, the statement des[0] = src[0] is undefined behavior; you're trying to change a constant there!
Any decent compiler should actually warn you about the implicit conversion from const char * to char *...
If using C++, consider using std::string instead of char *, and std::cout instead of printf.
Section 2.13.4 of ISO/IEC 14882 (Programming languages - C++) says:
A string literal is a sequence of characters (as defined in 2.13.2) surrounded by double quotes, optionally beginning with the letter L, as in "..." or L"...". A string literal that does not begin with L is an ordinary string literal, also referred to as a narrow string literal. An ordinary string literal has type “array of n const char” and static storage duration (3.7), where n is the size of the string as defined below, and is initialized with the given characters. ...
Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation defined. The effect of attempting to modify a string literal is undefined.
In C, string literals such as "123" are stored as arrays of char (const char in C++). These arrays are stored in memory such that they are available over the lifetime of the program. Attempting to modify the contents of a string literal results in undefined behavior; sometimes it will "work", sometimes it won't, depending on the compiler and the platform, so it's best to treat string literals as unwritable.
Remember that under most circumstances, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T" whose value is the location of the first element in the array.
Thus, when you write
char *src = "123";
char *des = "abc";
the expressions "123" and "abc" are converted from "3-element array of char" to "pointer to char", and src will point to the '1' in "123", and des will point to the 'a' in "abc".
Again, attempting to modify the contents of a string literal results in undefined behavior, so when you write
des[0] = src[0];
the compiler is free to treat that statement any way it wants to, from ignoring it completely to doing exactly what you expect it to do to anything in between. That means that string literals, or a pointer to them, cannot be used as target parameters to calls like strcpy, strcat, memcpy, etc., nor should they be used as parameters to calls like strtok.
vinaygarg: That means the des[0] is not being initialized. As src is pointing to the first element of the string. I guess by rules this should work.
Firstly you must remember that *src and *dst are defined as pointers, nothing more, nothing less.
So you must then ask yourself what exactly "123" and "abc" are and why it cannot be altered? Well to cut a long story short, it is stored in application memory, which is read-only. Why? The strings must be stored with the program in order to be available to your code at run time, in theory you should get a compiler warning for assigning a non-const char* to a const char *. Why is it read-only? The memory for exe's and dll's need to be protected from being overwritten somehow, so it must be read-only to stop bugs and viruses from modifying executing code.
So how can you get this string into modifiable memory?
// Copying into an array.
const size_t BUFFER_SIZE = 256;
char buffer[BUFFER_SIZE];
strcpy(buffer, "abc");
strncpy(buffer, "abc", BUFFER_SIZE-1);
I have two pointers to the same C string. If I increment the second pointer by one, and assign the value of the second pointer to that of the first, I expect the first character of the first string to be changed. For example:
#include "stdio.h"
int main() {
char* original_str = "ABC"; // Get pointer to "ABC"
char* off_by_one = original_str; // Duplicate pointer to "ABC"
off_by_one++; // Increment duplicate by one: now "BC"
*original_str = *off_by_one; // Set 1st char of one to 1st char of other
printf("%s\n", original_str); // Prints "ABC" (why not "BBC"?)
*original_str = *(off_by_one + 1); // Set 1st char of one to 2nd char of other
printf("%s\n", original_str); // Prints "ABC" (why not "CBC"?)
return 0;
}
This doesn't work. I'm sure I'm missing something obvious - I have very, very little experience with C.
Thanks for your help!
You are attempting to modify a string literal. String literals are not modifiable (i.e., they are read-only).
A program that attempts to modify a string literal exhibits undefined behavior: the program may be able to "successfully" modify the string literal, the program may crash (immediately or at a later time), a program may exhibit unusual and unexpected behavior, or anything else might happen. All bets are off when the behavior is undefined.
Your code declares original_string as a pointer to the string literal "ABC":
char* original_string = "ABC";
If you change this to:
char original_string[] = "ABC";
you should be good to go. This declares an array of char that is initialized with the contents of the string literal "ABC". The array is automatically given a size of four elements (at compile-time), because that is the size required to hold the string literal (including the null terminator).
The problem is that you can't modify the literal "ABC", which is read only.
Try char[] original_string = "ABC", which uses an array to hold the string that you can modify.
How come when I use the following method, to be used to convert all the characters in a string to uppercase,
while (*postcode) {
*postcode = toupper(*postcode);
postcode++;
}
Using the following argument works,
char wrong[20];
strcpy(wrong, "la1 4yt");
But the following, doesn't, despite them being the same?
char* wrong = "la1 4yt";
My program crashes in an attempt to write to an illegal address (a segfault, I presume). Is it an issue with not mallocing? Not being null-terimanted? It shouldn't be...
Through debugging I notice it crashes on the attempt to assign the first character as its uppercase.
Any help appreciated!
char* wrong = "la1 4yt";
This declares a pointer to a string constant. The constant cannot be modified, which is why your code crashes. If you wrote the more pedantic
const char* wrong = "la1 4yt"; // Better
then the compiler would catch the mistake. You should probably do this any time you declare a pointer to a string literal rather than creating an array.
This, on the other hand, allocates read/write storage for twenty characters so writing to the space is fine.
char wrong[20];
If you wanted to initialize it to the string above you could do so and then would be allowed to change it.
char wrong[20] = "la1 4yt"; // Can be modified
char wrong[] = "la1 4yt"; // Can be modified; only as large as required
char * whatever = "some cont string";
Is read-only.
In the second variant, "la1 4yt" is a constant and therefore is in a read-only segment. Only the pointer (wrong) to the constant is writeable. That's why you get the segfault. In the first example however, everything is writable.
This one might be interesting: http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/
See Question 8.5 in the C FAQ list.
When you do
char wrong[20] = "la1 4yt";
the compiler copies the elements of the string literal {'l', 'a', '1', ' ', '4', 'y', 't', '\0'} to the corresponding elements of the wrong array; when you do
char *wrong = "la1 4yt";
the compiler assigns to wrong the address of the string literal.
String literals are char[] (arrays of char), not const char[] ... but you cannot change them!!
Quote from the Standard:
6.4.5 String literals
6 It is unspecified whether these arrays are distinct provided
their elements have the appropriate values. If the program
attempts to modify such an array, the behavior is undefined.
When I use a string literal to initialize a char *, I usually also tell the compiler I will not be changing the contents of that string literal by adding a const to the definition.
const char *wrong = "la1 4yt";
Edit
Suppose you had
char *test1 = "example test";
char *test2 = "test";
And the compiler created 1 single string literal and used that single string literal to initialize both test1 and test2. If you were allowed to change the string literal ...
test1[10] = 'x'; /* attempt to change the 's' */
printf("%s\n", test2); /* print "text", not "test"! */