This question already has answers here:
Assigning strings to arrays of characters
(10 answers)
Closed 3 years ago.
I want to store a string "hello" in an array of characters char arr[10]
when I run the following code:
#include <stdio.h>
int main(void)
{
char arr[10] = "Hello";
printf("%s", arr);
}
The output is generated fine.
But when this code below is run, I get an error
#include <stdio.h>
int main (void)
{
char arr[10];
char * str = "Hello";
arr = str;
printf("%s", arr);
}
Why is that in the first case the string can be stored in the array and not in the second case?
Is there a way I can store "hello" in the second case?
You should use strncpy() or even better strlcpy() if you are on a BSD system or macOS and portability is not the main concern.
In C, char *p means a pointer to a character string. While writing the following
char arr[10];
char * str = "Hello";
arr = str;
you might have thought that the character string stored in the memory location pointed by str would be copied over to the buffer arr, but C does not do this for you.
The code below does what you want
#include <stdio.h>
#include <string.h>
#define BUFSIZ 10
int main(){
char arr[BUFSIZ];
const char *str=“Hello”; /* I used const here */
strncpy(arr, str, BUFSIZ);
printf(“%s\n”, arr);
return 0;
}
Use strncpy or strlcpy instead of strcpy. Documentation for strncpy is here.
The strcpy is the way to do it, as noted above. You get an error for
arr = str;
in your given code because you are attempting to assign an array, and C does not allow arrays to be assigned. In your first part, the declaration you give
char arr[10] = "Hello";
is legal because it is considered an initialization (since it's in a declaration), not an assignment. That is allowed.
C is not always a bundle of consistency.
To copy a string in C, use strcpy:
char arr[10];
char * str = "Hello";
strcpy(arr, str);
printf("%s\n", arr);
Don't forget to #include <string.h>, which is required for you to have access to this function.
char arr[10] means that arr can be changed;
char * str = "Hello" equals to const char* str = "Hello", so it can not be changed.
so arr = str will occur error.
You should check the memory allocation mechanism in C.
This is initialization of char array; there are special rules
char x[] = "foobar";
This is assignment to a pointer
char *p;
p = "foobar"; // char *p = "foobar"; initialization of pointer
There is no direct way to do assignment of a value to an array of char. You need to assign each individual element
char x[7];
x[0] = 'f'; x[1] = 'o'; x[2] = 'o';
x[3] = 'b'; x[4] = 'a'; x[5] = 'r'; x[6] = 0;
or use a function to do that for you
strcpy(x, "foobar");
Related
I have an array of char and I'm trying to have a string literal with the same chars in the array.
I tried strcpy, and try =, and I tried what I did in the following code. But it doesn't seem to work or I'm understanding something.
char s1[10]="Youssef";
char *s2
while(*s2!='\0')
*s2++=*s1++;
printf("%s",s2);
Process doesn't return.
String literals are read only.
In any case, what you are trying to do seems you are confused.
A string literal: char *sl = "string literal";
An uninitialized char pointer: char *s2;
In order to do the copy you like, you first need to allocate memory for the string.
Moreover, you cannot do pointer arithmetics with an array. Arrays and pointers are not the same thing!
Furthermore, you should remember the origin of s2 pointer, since after incrementing it until the copy is complete, you would then need to reset the pointer.. Exercise: Think what would happen if you did the copy in a function (preferably named mystrcpy`)...
Complete example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char s1[10]="Youssef";
char *s2 = malloc(sizeof(char) * (strlen(s1) + 1)); // +1 for the NULL-terminator
int i = 0;
char *origin_s2 = s2;
while(s1[i] != '\0')
*s2++ = s1[i++];
*s2 = '\0';
s2 = origin_s2;
printf("%s\n", s2);
return 0;
}
Output:
Youssef
PS: It is highly recommended to check if the dynamic allocation of the memory was successful (check if return value of malloc() is not NULL).
I am trying to perform swap operation as shown in below program, but it seems to crash when I am copying the element b into a (line 3 in swap() method) - this happens if the input is a char string i.e, char *str; If it is a character array instead (as in char str[];) the swap operation works fine.
#include<stdio.h>
void swap(char *a, char *b)
{
char tmp;
tmp = *a;
*a = *b; /* crash occurs here */
*b = tmp;
}
void func(char *a)
{
swap(a+1, a+2);
}
int main()
{
char *str = "abc";
// char str[] = "abc"; /* with this char array, the above swap func works */
func(str);
}
I think this is related to some C string rules that I seem to be unaware of. Please help!
String literals are read-only, trying to modify a string literal leads to undefined behavior.
Simplest solution? Declare it as an array instead:
char str[] = "abc";
char *str = "abc";
Above puts the string in the constant data section (also known as .rdata) of the program.As this is treated as constant data, it can not be modified
char str[] = "abc";
Above puts the string in the stack area of the program, as declared inside the function scope.This data can be modified.
As this is about the storage of string data, you are getting Crash in first declaration.
'char *str = "abc";'
The above places the abc in read only memory. So it cannot be modified.
'char str[]="abc";' is placed in stack. so it can be modified.
I am trying to understand why the following code is illegal:
int main ()
{
char *c = "hello";
c[3] = 'g'; // segmentation fault here
return 0;
}
What is the compiler doing when it encounters char *c = "hello";?
The way I understand it, its an automatic array of char, and c is a pointer to the first char. If so, c[3] is like *(c + 3) and I should be able to make the assignment.
Just trying to understand the way the compiler works.
String constants are immutable. You cannot change them, even if you assign them to a char * (so assign them to a const char * so you don't forget).
To go into some more detail, your code is roughly equivalent to:
int main() {
static const char ___internal_string[] = "hello";
char *c = (char *)___internal_string;
c[3] = 'g';
return 0;
}
This ___internal_string is often allocated to a read-only data segment - any attempt to change the data there results in a crash (strictly speaking, other results can happen as well - this is an example of 'undefined behavior'). Due to historical reasons, however, the compiler lets you assign to a char *, giving you the false impression that you can modify it.
Note that if you did this, it would work:
char c[] = "hello";
c[3] = 'g'; // ok
This is because we're initializing a non-const character array. Although the syntax looks similar, it is treated differently by the compiler.
there's a difference between these:
char c[] = "hello";
and
char *c = "hello";
In the first case the compiler allocates space on the stack for 6 bytes (i.e. 5 bytes for "hello" and one for the null-terminator.
In the second case the compiler generates a static const string called "hello" in a global area (aka a string literal, and allocates a pointer on the stack that is initialized to point to that const string.
You cannot modify a const string, and that's why you're getting a segfault.
You can't change the contents of a string literal. You need to make a copy.
#include <string.h>
int main ()
{
char *c = strdup("hello"); // Make a copy of "hello"
c[3] = 'g';
free(c);
return 0;
}
I know this has been asked thousands of times but I just can't find the error in my code. Could someone kindly point out what I'm doing wrong?
#include <stdlib.h>
#include <string.h>
void reverseString(char *myString){
char temp;
int len = strlen(myString);
char *left = myString;
// char *right = &myString[len-1];
char *right = myString + strlen(myString) - 1;
while(left < right){
temp = *left;
*left = *right; // this line seems to be causing a segfault
*right = temp;
left++;
right--;
}
}
int main(void){
char *somestring = "hello";
printf("%s\n", somestring);
reverseString(somestring);
printf("%s", somestring);
}
Ultimately, it would be cleaner to reverse it in place, like so:
#include <stdio.h>
#include <string.h>
void
reverse(char *s)
{
int a, b, c;
for (b = 0, c = strlen(s) - 1; b < c; b++, c--) {
a = s[b];
s[b] = s[c];
s[c] = a;
}
return;
}
int main(void)
{
char string[] = "hello";
printf("%s\n", string);
reverse(string);
printf("%s\n", string);
return 0;
}
Your solution is essentially a semantically larger version of this one. Understand the difference between a pointer and an array. The standard explicitly states that the behviour of such an operation (modification of the contents of a string literal) is undefined. You should also see this excerpt from eskimo:
When you initialize a character array with a string constant:
char string[] = "Hello, world!";
you end up with an array containing the string, and you can modify the array's contents to your heart's content:
string[0] = 'J';
However, it's possible to use string constants (the formal term is string literals) at other places in your code. Since they're arrays, the compiler generates pointers to their first elements when they're used in expressions, as usual. That is, if you say
char *p1 = "Hello";
int len = strlen("world");
it's almost as if you'd said
char internal_string_1[] = "Hello";
char internal_string_2[] = "world";
char *p1 = &internal_string_1[0];
int len = strlen(&internal_string_2[0]);
Here, the arrays named internal_string_1 and internal_string_2 are supposed to suggest the fact that the compiler is actually generating little temporary arrays every time you use a string constant in your code. However, the subtle fact is that the arrays which are ``behind'' the string constants are not necessarily modifiable. In particular, the compiler may store them in read-only-memory. Therefore, if you write
char *p3 = "Hello, world!";
p3[0] = 'J';
your program may crash, because it may try to store a value (in this case, the character 'J') into nonwritable memory.
The moral is that whenever you're building or modifying strings, you have to make sure that the memory you're building or modifying them in is writable. That memory should either be an array you've allocated, or some memory which you've dynamically allocated by the techniques which we'll see in the next chapter. Make sure that no part of your program will ever try to modify a string which is actually one of the unnamed, unwritable arrays which the compiler generated for you in response to one of your string constants. (The only exception is array initialization, because if you write to such an array, you're writing to the array, not to the string literal which you used to initialize the array.) "
the problem is here
char *somestring = "hello";
somestring points to the string literal "hello". the C++ standard doesn't gurantee this, but on most machines, this will be read-only data, so you won't be allowed to modify it.
declare it this way instead
char somestring[] = "hello";
You are invoking Undefined Behavior by trying to modify a potentially read-only memory area (string literals are implicitly const -- it's ok to read them but not to write them). Create a new string and return it, or pass a large enough buffer and write the reversed string to it.
You can use the following code
#include<stdio.h>
#include<string.h>
#include<malloc.h>
char * reverse(char*);
int main()
{
char* string = "hello";
printf("The reverse string is : %s", reverse(string));
return 0;
}
char * reverse(char* string)
{
int var=strlen(string)-1;
int i,k;
char *array;
array=malloc(100);
for(i=var,k=0;i>=0;i--)
{
array[k]=string[i];
k++;
}
return array;
}
I take it calling strrev() is out of the question?
Your logic seems correct. Instead of using pointers, it is cleaner to deal with char[].
void reverse(char *str){
int i,j;
char temp;
for(i=0,j=strlen(str)-1; i<j; i++, j--){
temp = *(str + i);
*(str + i) = *(str + j);
*(str + j) = temp;
printf("%c",*(str + j));
}
}
int main (int argc, char const *argv[])
{
char *str = "Shiv";
reverse(str);
printf("%s",str);
return 0;
}
When I use char *str = "Shiv" the lines in the swapping part of my reverse function i.e str[i]=str[j] dont seem to work, however if I declare str as char str[] = "Shiv", the swapping part works? What is the reason for this. I was a bit puzzled by the behavior, I kept getting the message "Bus error" when I tried to run the program.
When you use char *str = "Shiv";, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.
When you use char str[] = "Shiv";, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.
The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.
char *str = "Shiv";
This should be :
const char *str = "Shiv";
And now you'll have an error ;)
Try
int main (int argc, char const *argv[])
{
char *str = malloc(5*sizeof(char)); //4 chars + '\0'
strcpy(str,"Shiv");
reverse(str);
printf("%s",str);
free(str); //Not needed for such a small example, but to illustrate
return 0;
}
instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.
String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with
char *str = "Shiv";
variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.
The
char str[] = "Shiv";
variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.
P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been
const char *str = "Shiv";
(note the extra 'const').
String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.
Declare str as an array instead:
char str[] = "Shiv";
This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str are modifiable.
When I want to use a pointer to a string literal, I usually declare it const. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal
const char *str = "Shiv";
Imagine you could do the same with integers.
/* Just having fun, this is not C! */
int *ptr = &5; /* address of 5 */
*ptr = 42; /* change 5 to 42 */
printf("5 + 1 is %d\n", *(&5) + 1); /* 6? or 43? :) */
Quote from the Standard:
6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.
char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.
Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.
Typically, it is a bad idea to do in-place modification of constants.
In any case, this post explains this situation pretty clearly.
The first (char[]) is local data you can edit
(since the array is local data).
The second (char *) is a local pointer to
global, static (constant) data. You
are not allowed to modify constant
data.
If you have GNU C, you can compile
with -fwritable-strings to keep the
global string from being made
constant, but this is not recommended.