char* and char[] with strcat() - c

My Question is char *string1 cannot be modified, then why they have syntax like
char *strcat(char *string1, const char *string2) ??
#include<stdio.h>
#include<string.h>
int main(void)
{
const char *p="Everyone";
char *a="Hello ";
printf("%s",strcat(a,p));
return 0;
}
Output: Segmentation fault (core dumped)
#include<stdio.h>
#include<string.h>
int main(void)
{
const char *p="Everyone";
char a[20]="Hello ";
printf("%s",strcat(a,p));
return 0;
}
Output: Hello Everyone
In snippet 1,char* stores in read-only memory, so we cannot modify(Here the modification is concatenation) I think that's why it shows segmentation fault
but syntax for strcat() is char *strcat(char *string1, const char *string2) .

The problem is not in strcat. The problem is that C90, due to backwards compatibility, decided to type the string literals as arrays of non-const characters, but specified that the behaviour when attempting to modify the characters in the said arrays would be undefined. After all, the entire const keyword was introduced in 80s being adopted from C++!
Even today, many compilers, like GCC, have a (questionable) option -fwritable-strings that makes string literals modifiable, just like in some early C compilers.
Notice that nothing stops you from writing
const char *a = "Hello ";
and then the strcat would complain loudly.

My Question is char *string1 cannot be modified, then why they have syntax like
char *strcat(char *string1, const char *string2) ??
Well, it depends on the argument you pass as the first parameter to the call. It's the requirement of the function and responsibility of the programmer to ensure to pass the first parameter as a pointer to memory which
can be modified (writable)
has enough memory to store the concatenated value.
The function signature is fine, it accepts a pointer to a char (array, long enough as per requirement).

Related

I got issue in strcpy in C, is there any mistake in my code?

#include<stdio.h>
#include<string.h>
int main() {
char oldS[] = "Hello";
char newS[] = "Bye";
strcpy(newS, oldS);
puts(newS);
}
I was trying to learn string.h in C, will doing strcpy I am unable to get the output.
output is like
koushik#Koushiks-MacBook-Air C % cd "/Users/koushik/Documents/
C/" && gcc stringcopy.c -o stringcopy && "/Users/koushik/Docum
ents/C/"stringcopy
zsh: illegal hardware instruction "/Users/koushik/Documents/C/"stringcopy
When you use strcpy(), the size of the destination string should be large enough to store the copied string. Otherwise, it may result in undefined behavior.
As you've declared the char array without specifying the size, it was initialized with the size of the string "Bye", which is smaller than the string "Hello". That's why problem occurred.
Solution:
#include<stdio.h>
#include<string.h>
int main()
{
char oldS[6] = "Hello";
char newS[6] = "Bye";
strcpy(newS, oldS);
puts(newS);
}
You need to allocate space to use strcpy either way with creating an array with a suffisent size or using malloc

What is the issue with this C code which has a error?

It is a code written to copy one pointer to another.
ERROR is Segmentation error (core Dumped)
#include<stdio.h>
char strcp(char *,char *);
int main()
{
char *p="string",*q;
printf("%s",p);
strcp(p,q);
printf("%s",q);
return 0;
}
char strcp(char *p,char *q)
{
int i;
for(i=0;*(p+i)!='\0';i++)
*(p+i)=*(q+i);
}
char *p="string"...
strcp(p,q);
What p points to is a literal and literals are read-only. Trying to copy anything to it is forbidden (and causes a segmentation fault).
...and q is not initialized, another possible cause of the seg fault.
The problem with this algorithm is an implicit assumption it makes about pointers: char *q is not a string, it is a pointer to character. It can be treated as a string if you allocate space and place a null-terminated sequence of characters into it, but your code does not do it.
You can allocate space to q with malloc, like this:
char *p="string";
char *q=malloc(strlen(p)+1);
In addition, your version of strcpy reads null terminator from a wrong pointer, and does not null-terminate the copied string:
char strcp(char *p, char *q)
{
int i;
for(i=0;*(q+i)!='\0';i++) // <<== Fix this
*(p+i)=*(q+i);
*(p+i) = '\0'; // <<== Add this line
}
As the other answers have indicated the problem starts* with char *p="string",*q;.
The Literal "string" compiles to the equivalent:
const char foo[7] = {'s','t','r','i','n','g','\0'}; why *\0
As you might see further in you code you're trying to copy data to a const a\rray. Which is illegal.
But you're playing C, you have implicitly casted the const char foo[] to a char *p, right there during initialization.
C is not type safe because it's tightly coupled to the actual instruction on the hardware. Where types don't exist anymore, just widths. But that is for another topic.
*It's not the only flaw. I tossed in a few explanatory wiki links. Because the question shows you're a novice programmer. Keep up the work.

C char pointer, char pointer copying char pointer. Whether it can be considered as a automatic / dynamic space creation in memory?

I write my own version of strcpy(). I learn it from http://pweb.netcom.com/~tjensen/ptr/ch3x.htm .
So.. here is the source code:
#include <stdio.h>
char *my_strcpy(char *dst, char *src);
char *my_strcpy(char *dst, char *src)
{
char *ptr = dst;
while (*src)
{
*ptr++ = *src++;
}
*ptr = '\0';
return dst;
}
int main(int argc, const char *argv[])
{
char strA[] = "Awesome string! Yes it is G-String!";
char strB[20];
my_strcpy(strB, strA);
puts(strB);
return 0;
}
In function main() i experiment to change:
char strA[] = "Awesome string! Yes it is G-String!";
char strB[20];
become
char *strA = "Awesome string! Yes it is G-String!";
char *strB;
And, yay! it works! Then the question is, How char *strB and char *ptr = dst (inside my_strcpy() ) work?
In my understanding, they not have more than one space in memory. They only have one space in memory since char *strB not initialized as like char *strA . Whether it can be considered as a automatic / dynamic space creation in memory? How the data stored?
Please enlightenment
Thank you :)
In both char strB[20]; and uninitialized char * strB, you'll face Undefined behaviour.
In the former case, you'll be writing past allocated memory.
In the later case, you'll try to access uninitialized memory.
However, as per the standard function comparison, my_strcpy() function behaviour is okay. If you want to add some preventive measure to your version of the code, consider at least adding a Check for NULL incoming pointer for both source and destination.
If
char *strA = "Awesome string! Yes it is G-String!";
char *strB;
works then it is undefined behvaior. strA is a string literal and is read-only.
Whereas strB is just a pointer and is not pointing to any valid memory location and accessing/writing unallocated memory is undefined behvaior.
it can be considered as a automatic / dynamic space creation in memory?
No, in none of your examples the function my_strcpy() allocates any memory for the destination "string".
It is undefined behavior.
char *strA = "Awesome string! Yes it is G-String!";// It is stored in a read only memory.
char *strB;// it is uninitialized pointer and not pointing to any where.
In first case,
char strB[20];
It is also a undefined behavior. first string length greater that twenty.
I think there is a misunderstood on function prototype.
Do you know why have you writing this line ?
char *my_strcpy(char *dst, char *src);
This is a function prototype, it says to the compiler:
you will see a function named my_strcpy(char *dst, char *src)
but, if you see you need it (see Subroutine) before I define
it don't worry, I explain later how it works.
So write a function prototype following by definition of this function is a nonsense.
You could remove the function prototype or you could keep prototype if you write this:
#include <stdio.h>
char *my_strcpy(char *dst, char *src);
int main(int argc, const char *argv[])
{
[...]
my_strcpy(strB, strA);
[...]
}
char *my_strcpy(char *dst, char *src)
{
[...]
}
Because the compiler read line by line, from the top to the bottom.
So when it will be in main() at line my_strcpy(strB, strA);, if you remove char *my_strcpy(char *dst, char *src); before main() compiler will say:
I don't kown any my_strcpy(arg1, arg2) function so I stop there.
I hope this can help you!

char c1[ ]="abcde" works while char *c1="abcde" turns out wrong?

I was working on the "c programming language" exercise2.4, which deletes each character in s1 that matches any character in the string s2.Below is my code, it works. However,if I change the definition in Main function from char c1[ ]="abcde" to char *c1="abcde", it will turns out segmentation fault(core dumped). Any idea why?
#include<stdio.h>
#define UNREPEAT 1
#define REPEAT 0
void squeeze(char *s1,char *s2);
void main(){
char c1[]="abcde";
char c2[]="cd";
printf("c1 is %s\n",c1);
squeeze(c1,c2);
printf("the final result is %s\n",c1);
}
void squeeze(char *s1,char *s2){
int i,j,judge;
int k=0;
for(i=0;*(s1+i)!='\0';i++){
judge=UNREPEAT;
for(j=0;*(s2+j)!='\0';j++){
if (*(s1+i)==*(s2+j)){
judge=REPEAT;
break;}
}
if( judge==UNREPEAT){
* (s1+k)=*(s1+i);
k++;}
}
*(s1+k)='\0';
}
Because
char c1[] = "abcde";
declares an array, it's readable and writable and will always have 6 bytes (if you consider the terminating '\0') you can't extend it but of course you can use it to store less bytes.
While
char *c1 = "abcde";
is a static string literal it shall not be modified, you should always declare string literals using the const qualifier, that way the compiler would warn you if you try to modify its contents, which is illegal, just use
const char *c1 = "abcde";
char *c1="abcde"
This is a string literal which is read-only and in your function you try to change the contents of it so you might hit seg fault.
Whereas the other case
char c1[] = "abcde";
You are allocating memory on the stack whose contents can be modified.
PS: String literals are read-only

Can I initialize string after declaration?

Can I initialize string after declaration?
char *s;
s = "test";
instead of
char *s = "test";
You can, but keep in mind that with that statements you are storing in s a pointer to a read-only string allocated elsewhere. Any attempt to modify it will result in undefined behavior (i.e., on some compilers it may work, but often will just crash). That's why usually you use a const char * for that thing.
Yes, you can.
#include <stdio.h>
int
main(void)
{
// `s' is a pointer to `const char' because `s' may point to a string which
// is in read-only memory.
char const *s;
s = "hello";
puts(s);
return 0;
}
NB: It doesn't work with arrays.
#include <stdio.h>
int
main(void)
{
char s[32];
s = "hello"; // Syntax error.
puts(s);
return 0;
}
It is correct for pointers (as mentioned above) because the string inside quotes is allocated from the compiler at compile time, so you can point to this memory address. The problems comes when you try change its contents or when you have a fixed size array that want to point there

Resources