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)
Difference between declared string and allocated string
(3 answers)
Closed 8 years ago.
I have the following code. I initialized 2 pointers, one at the beginning and another at the ending of a string. After every step, I increment the 1st pointer and decrement the second pointer. I copy the value of first pointer into the second if the value obtained by dereferencing 1st pointer is less than the value obtained by dereferencing 2nd pointer.
#include <stdio.h>
#include <string.h>
int main() {
char *word="aacdbc";
char *p=word;
char *q=word+(strlen(word)-1);
printf("\n%s\n",word);
int i;
for(i=1;i<=strlen(word)-1;++i) {
if(*p<*q) {
*q=*p;
}
++p;
--q;
}
printf("\n%s\n",word);
return 0;
}
But the code shows a "Segmentation fault error". In which line did I make a mistake?
String literals in C (and C++) are immutable. So your attempt to change the string literal pointed to by the variable word
char *word = "aacdbc";
has undefined behaviour.
Change the definition from a pointer to an array
char word[] = "aacdbc";
The program could look the following way
#include <stdio.h>
int main( void )
{
char word[] = "aacdbc";
char *p = word;
char *q = word+ + sizeof( worrd ) - 1;
printf( "\n%s\n", word );
while ( p < q && p < --q )
{
if ( *p < *q ) *q = *p;
++p;
}
printf( "\n%s\n", word );
return 0;
}
Because word is a pointer to a constant (read-only) characters sequence. In other words, you can't change the contents of a string literal.
If you want to change its contents, you should declare word as an array of chars:
char word[]="aacdbc";
With that small change, the segfault should disappear.
Related
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 9 months ago.
I want to create void function that will change existing dynamic (or static) array. How this can be implemented in C and C++? How to properly pass arguments to such functions? For example i want to reverse char array
//function that reverse the string
void reverseString(char* str)
{
char t;
int i, j;
for (j = 0; str[j] != '\0'; j++)
{
}
j -= 1;
for (int i = 0; i < j; i++, j--)
{
t = str[i];
str[i] = str[j];
str[j] = t;
}
}
int main()
{
char* name = "Ani?321";
reverseString2(&name);
printf("%s", name);
}
running this code: Exception thrown at 0x796028BC (ucrtbased.dll) in Strings.exe: 0xC0000005: Access violation reading location 0x00E87B51.
When i changing function parameter from char* to char** -> Run-Time Check Failure #2 - Stack around the variable 'str' was corrupted. (pointing to the closing curly bracket of the main function)
You have two major problems:
Your pointer name is pointing to a literal string. Such strings can't be modified, and any attempt to do so leads to undefined behavior. You solve this issue by using an array instead:
char name[] = "Ani?321";
The second problem is that you pass a pointer to the pointer to your function. The type of &name (in your current code) is char **, which is not the correct type and definitely not the correct pointer. You should pass plain name as argument (which will also work when you solve the first problem).
Well, you have declared a string literal which you can't modify. Declare it like this instead char name[] = "Ani?321";
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 1 year ago.
Good day,
I have a function ft_strupcase which takes in a char*, upper-cases it, and returns the parameter. The issue arose during the testing, namely using the function in a main. The following program results in a segmentation fault:
int main()
{
char *hey = "hEy";
printf("%s\n", ft_strupcase(hey));
}
whereas this variation doesn't:
int main()
{
char hey[] = "hEy";
printf("%s\n", ft_strupcase(hey));
}
Isn't *str and str[] the same? Doesn't str[i] = *(str + i)? Why do I encounter a segfault then?
int main()
{
char *hey = "hEy";
printf("%s\n", ft_strupcase(hey));
}
In this code, hey points to a string literal, which is a constant. Then ft_strupcase modifies the thing you pass it a pointer to. So this code attempts to modify a constant.
You can't modify a constant. That's what it means for something to be constant.
int main()
{
char hey[] = "hEy";
printf("%s\n", ft_strupcase(hey));
}
Here, hey is an array of characters, initialized from a constant. The array is modifiable since the array entries are not constants.
If you have int i = 3;, you can modify i, but you can't modify the 3. The first code tries to modify the thing on the right side of the = by passing a function that modifies the thing pointed to a pointer to it. The second code modifies the thing on the left side of the =, which is perfectly legal.
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 1 year ago.
I am trying to understand what is wrong with my code and my understanding of pointers, arrays and string in C.
I tried to create an array of strings, to be able to loop over it and to test any functions that take a string as a parameter.
In this case, i'm trying to check my private implantation of memset called Memset.
This is my code:
#include <stdio.h>
#include <string.h>
/*First Try, did not work: */
/*const char * strings_array[] = {*/
/* "First string",*/
/* "213123Second_string3",*/
/* "",*/
/* "-3",*/
/* "s",*/
/*};*/
/* Second try, also does not work: */
const char **strings_array = (char *[]){"a", "b", "c"};
int main ()
{
while(*strings_array)
{
char *string = strings_array;
printf( "Before Memset, target is \"%s\"\n", *string );
if (NULL == Memset(*string, '$', 4))
{
fprintf(stderr,"Memset failed!\n");
}
printf( "After Memset, target is \"%s\"\n\n", *string );
++strings_array;
}
return (0);
}
I know that a string in C is not a type but a char *.
But it is also a string literal, which means I can't change it, and can only read it.
That's why it's not working?
Because I'm passing it to Memset and Memset tries to change it while it can not be changed because it's a string literal?
This is my implantation of my Memset function:
void *Memset(void *str, int c, size_t n)
{
unsigned char *string = str;
if (NULL == str)
{
return (NULL);
}
while(n > 0)
{
*string++ = (unsigned char) c;
--n;
}
return (str);
}
Your assesment is correct. You're creating an array of char * and initializing those pointers the the address of string constants, and string constants cannot be modified.
Instead of defining an array of char *, define a 2D array of char. While you use string constants to initialize the array, the array itself it writable.
char strings_array[][50] = {
"First string",
"213123Second_string3",
"",
"-3",
"s",
};
Note that for a multidimensional array, only the first dimension can have the size omitted if there is an initializer.
The first mistake that popped out at me was that in Memset you indirectly cast a void* to unsigned char *. I would change this to an explicit cast: unsigned char *string = (unsigned char *)str;
Secondly, you are absolutely correct: string literals cannot be modified. An attempt to modify a string literal would result in an error.
To test this code, I would try to allocate a string array on the heap, load some test strings into there, and then pass your string pointers from that array into your Memset function.
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)
Why is this string reversal C code causing a segmentation fault? [duplicate]
(8 answers)
Closed 4 years ago.
I am trying to reverse a string in-place using two pointers to the same string. First one(char *p) points to the starting location of the string and second one(char *q) points to the ending location of the string. So when I tried to debug using gdb, I get am getting segmentation fault at line 16.
When I tried to print the values of *p and *q, it works fine. Why am I getting segfault while I'm still able to access those location?
Breakpoint 1, main () at reverse.c:16
16 *q = *p;
(gdb) print p
$1 = 0x5555555547e4 "hello"
(gdb) print q
$2 = 0x5555555547e8 "o"
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
0x00005555555546db in main () at reverse.c:16
16 *q = *p;
The actual code of the program is
#include<stdio.h>
int main() {
char *array = "hello";
char *p=&array[0];// pointer to the first element
// Make q point to last value of the array
char *q = &array[0];
while(*q) q++;
char temp;
q--; // move left so that we don't point to `\0`
while(p<q){
temp = *p;
*q = *p;
*p = temp;
p++;q--;
}
printf(" Done reversing \n");
}
Your string, which you call array, is not really a char array, but a string literal, which is, depending on the platform, not writable. So change it to
char array[] = "Hello";
There is a difference between char *array = "string" and char array[] = "string".
char *array = "string" puts "string" in read-only parts of the memory, and makes array point to it. Thus, any attempt to change the contents of the memory array is pointing to will result in a seg fault (illegal in other words).
char array[] = "string" puts "string" in the read-only parts of the memory and copies it to a newly allocated memory on the stack where array is pointing to. Thus, making changes to the memory array is pointing to legal.
You also might want to take a look at this post.
You are trying to change the string literal
char *array = "hello";
pointed to by the pointer array.
Though in C (opposite to C++) string literals have types of non-constant character arrrays nevertheless you may not change string literals. Any attempt to change a string literal results in undefined behavior.
You should declare a character array initializing it with the string literal. For example
char array[] = "hello";
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
char array[] = "hello";
puts( array );
char *q = array;
while ( *q ) ++q;
for ( char *p = array; p < --q; ++p )
{
char c = *p;
*p = *q;
*q = c;
}
puts( array );
return 0;
}
Its output is
hello
olleh
Also the code snippet in your program that swaps characters is wrong
temp = *p;
*q = *p;
*p = temp;
There must be
temp = *p;
*p = *q;
*q = temp;
And as the variable temp is used only within the while loop its declarative region should be restricted by the block scope of the while loop.
while(p<q){
char temp = *p;
*p = *q;
*q = temp;
p++;q--;
}
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
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 9 years ago.
#include <stdio.h>
#include <conio.h>
void test(char *p)
{
p = p + 1;
*p = 'a';
}
int main()
{
char *str = "Hello";
test(str);
printf("%s", str);
getch();
return 0;
}
When I run this code it gives segmentation error ? why is this happening. The const theory is not clear to me... whereas if I declare str as char str[], it does the job. Are they not both basically the same things ?
str is pointing to a string literal, you are attempting to modify the string literal in the function test on this line:
*p = 'a';
It is undefined behavior to attempt to modify a string literal. You can alternatively, make a copy of the string literal into a array as follows:
char str[] = "Hello";
now it is perfectly ok to modify str. From the draft C99 standard, under section 6.4.5 String literals paragraph 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.
*p = 'a';
The problem is the above statement tries to modify the read only segment. String literal "Hello" resides in read only segment and can not be modified.
char str[] = "Hello";
The above statement copies Hello to str character array and the array contents can be modified.