character pointer - c

Why this code does not work?
int main(){
char *str ="abcde";
scanf("%s",str);
printf("%s",str);
}
but this works?
int main(){
char str[] ="abcde";
scanf("%s",str);
printf("%s",str);
}`

In the first code, you declare a pointer, which points to a string literal: "abcde".
This might be a constant, and you will not be able to change it.
The second code is declaring an array and filling it with ['a','b',c','d','e','\0'], and is not a constant - so you can change it.

Because char *str ="abcde"; is a pointer to string literal which is most likely stored in read-only memory.
char str[] ="abcde"; is an array initialized with "abcde".
You should also check out Difference between char* and char[]

When string value is directly assigned to a pointer, it’s stored in a
read only block(generally in data segment) that is shared among
functions
char *str = "GfG";
...
char str[] = "GfG"; /* Stored in stack segment like other auto
variables */ *(str+1) = 'n'; /* No problem: String is now GnG */
http://www.geeksforgeeks.org/archives/5328

Related

Should I manually allocate string ending char '\0' in c?

I'm new to c, and confused by string ending char '\0', should I allocate it?
for example, I want to store a string with a max length of 6;
If I use array, should I use char str[6] or char str[7]?
char as[3] = "abc";
printf("%s\n", as);
//seems no problem
If I use char pointer, should I use char *str = malloc(6) or char *str = malloc(7)?
For an array that is pre-initialized, you don't need to write a number in the brackets. You can just write
char str[] = "this is my string";
And the compiler will automatically calculate the number of bytes needed.
But for malloc, you must add 1. Ex:
char *strdup(const char *str)
{
char *ret = malloc(strlen(str) + 1);
strcpy(ret, str);
return ret;
}
You should be using string length + 1. In your case you must use 7 while declaring the char array.
The example you provided would have worked because of the undefined behaviour shown by printf().
In addition to stackptr's answer:
If you are planning to overwrite your array:
char str[30] = "abc";
...
strcpy(str, "Hello world"); /* This will overwrite the content of "str" */
... the length of the array must be the maximum length of the string plus 1.
In the example above you may write strings of up to 29 characters length to the array.
Note that the following definition:
char str[] = "abc";
... implicitly creates an array of 4 characters length so you are limit to 3 characters.

copy one string in to other using pointer produce Garbage values why?

if take array it will be fine but as i used *str1 and str2 it does not work
#include <stdio.h>
void copystr(char* ,char*);
int main()
{
char *str1="xxx";
char *str2= "yyy";
copystr(str1, str2);
printf("\n %s",str2);
}
void copystr(char *dest,char *src)
{
while(*src!='\0')
*dest++=*src++;
*dest='\0';
return;
}
char *str = "some string"
Here str is a pointer pointing to a constant memory, which can't be edited and leads to undefined behaviour.
But If you declare like
char str2[] = "some string"
Now str2 above is pointing to a memory which is not constant and can be changed. Thus will work.
More explanation here:
char *array and char array[]
Destination string str1 is a string literal. String literals are non modifiable. Any attempt to modify it will invoke undefined behavior.

When to use char a[] over char p* and vice versa?

Lately I've been learning all about the C language, and am confused as to when to use
char a[];
over
char *p;
when it comes to string manipulation. For instance, I can assign a string to them both like so:
char a[] = "Hello World!";
char *p = "Hello World!";
and view/access them both like:
printf("%s\n", a);
printf("%s\n", p);
and manipulate them both like:
printf("%c\n", &a[6]);
printf("%c\n", &p[6]);
So, what am I missing?
char a[] = "Hello World!";
This allocates modifiable array just big enough to hold the string literal (including terminating NUL char). Then it initializes the array with contents of string literal. If it is a local variable, then this effectively means it does memcpy at runtime, every time the local variable is created.
Use this when you need to modify the string, but don't need to make it bigger.
Also, if you have char *ap = a;, when a goes out of scope ap becomes a dangling pointer. Or, same thing, you can't do return a; when a is local to that function, because return value will be dangling pointer to now destroyed local variables of that function.
Note that using exactly this is rare. Usually you don't want an array with contents from string literal. It's much more common to have something like:
char buf[100]; // contents are undefined
snprintf(buf, sizeof buf, "%s/%s.%d", pathString, nameString, counter);
char *p = "Hello World!";
This defines pointer, and initializes it to point to string literal. Note that string literals are (normally) non-writable, so you really should have this instead:
const char *p = "Hello World!";
Use this when you need pointer to non-modifiable string.
In contrast to a above, if you have const char *p2 = p; or do return p;, these are fine, because pointer points to the string literal in program's constant data, and is valid for the whole execution of the program.
The string literals themselves, text withing double quotes, the actual bytes making up the strings, are created at compile time and normally placed with other constant data within the application. And then string literal in code concretely means address of this constant data blob.
char * strings are read-only. They cannot be modified while char[] strings can be.
char *str = "hello";
str[0] = 't'; // This is an illegal operation
Whereas
char str[] = "hello"; str[0] = 't'; // Legal, string becomes tello

unexpected error on printing string

Why does this code produce an error? Shouldn't it output zbcde?
int main()
{
char *p="abcde";
*p='z';
printf("%s\n",p);
return 0;
}
You're trying to modify a string literal; it's undefined behavior.
Further explanation: "abcde" is not a char * but a const char *. You should do one of the following solutions:
char p[] = "abcde";
or
char *p = strdup("abcde");
(in the latter case, don't forget to free() p!)
char *p="abcde"; - This will keep the string abcde in text segement as read only data and the address will be kept in the local pointer variable p.
*p = 'z' will tries to replace the read only data a to z. Which is an undefined behaviour, which can leads to crash.
So declare the string as local char array variable as below.
char p[] = "abcde"
So allocate dynamic memory to keep the string like below.
char *p = strdup("abcde");
...
free(p);

Why does *(str+i) = *(str +j) not work here?

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.

Resources