Pra Sys
asked on
C Pointers and String constants
Hi,
Very basic question as I probably forgot how this works. I was testing rudimentary strcat function from K&R and I found different behavior while giving input in different manner -
#include <iostream>
using namespace std;
void strCat(char *s, char *t) {
while(*s)
s++;
while((*s++ = *t++))
;
}
int main() {
char p[] = "Hello ";
1-> char *s = "Hello "; //DO NOT WORK
2-> //s = p; //WORKS
3-> //char s[] = "Hello "; //WORKS
char *t = "world!";
strCat(s,t);
cout << s << endl;
return 0;
}
When I try to send string s as given on line by "1->", I get runtime exception. Otherwise if i try as per given on lines "2->" or"3->", it works!!!
Can anybody tell me why "1->" doesn't work??
Very basic question as I probably forgot how this works. I was testing rudimentary strcat function from K&R and I found different behavior while giving input in different manner -
#include <iostream>
using namespace std;
void strCat(char *s, char *t) {
while(*s)
s++;
while((*s++ = *t++))
;
}
int main() {
char p[] = "Hello ";
1-> char *s = "Hello "; //DO NOT WORK
2-> //s = p; //WORKS
3-> //char s[] = "Hello "; //WORKS
char *t = "world!";
strCat(s,t);
cout << s << endl;
return 0;
}
When I try to send string s as given on line by "1->", I get runtime exception. Otherwise if i try as per given on lines "2->" or"3->", it works!!!
Can anybody tell me why "1->" doesn't work??
the destination must be writeable and have sufficient space
ASKER
Why it is writable in char s[] case and not in char *s case??
The effect of attempting to modify a string literal is undefined.
In both cases, addressing beyond the bounds of an object is undefined
In both cases, addressing beyond the bounds of an object is undefined
ASKER
I know that. then why it works in case of char s[]?? I am using minGW g++ compiler on windows 8.
When behavior is undefined, the compiler is permitted to do anything.
Including overwriting something you haven't noticed yet.
By the way, K&R is an old standard, most C compilers use C89 or later, and your program does not even look like C because it uses C++ constructs.
By the way, K&R is an old standard, most C compilers use C89 or later, and your program does not even look like C because it uses C++ constructs.
ASKER
I am not using old compiler. It is a c++ program strcat function is from k&r. Can you rewrite the method which you think will work?
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main() {
char p[] = "Hello ";
char *t = "world!";
char *s = (char *)malloc(sizeof(p)+strlen( t));
strcpy(s,p);
strcat(s,t);
puts(s);
return 0;
}
or
#include <iostream>
using namespace std;
int main() {
char p[] = "Hello ";
const char *t = "world!";
string s(p);
s += t;
cout << s << endl;
return 0;
}
#include <string.h>
#include <stdio.h>
int main() {
char p[] = "Hello ";
char *t = "world!";
char *s = (char *)malloc(sizeof(p)+strlen(
strcpy(s,p);
strcat(s,t);
puts(s);
return 0;
}
or
#include <iostream>
using namespace std;
int main() {
char p[] = "Hello ";
const char *t = "world!";
string s(p);
s += t;
cout << s << endl;
return 0;
}
ASKER
Ok. Thanks. So direct pointer arithmetic won't work in new compilers on stack memory?
#include <string.h>
#include <stdio.h>
int main() {
char s[13] = "Hello ";
char *t = "world!";
strcat(s,t);
puts(s);
return 0;
}
#include <stdio.h>
int main() {
char s[13] = "Hello ";
char *t = "world!";
strcat(s,t);
puts(s);
return 0;
}
You apparently don't understand the difference between the declarations
char s[] = "Hello ";
char *t = "world!";
The first declares an array of (in this case) 7 chars (remember the \0 terminator!). The array is writable, so you could do things like
strcpy( s, "world!" ); /* This should work, and s[] now contains "world!\0" */
However, the second declaration defines t as a "pointer to char" and initializes it to point to the (anonymous) string "world!\0", which the compiler is entitled to put anywhere, including in the text (code) segment of your program, which is read-only. Therefore, trying to modify this will give you an error.
char s[] = "Hello ";
char *t = "world!";
The first declares an array of (in this case) 7 chars (remember the \0 terminator!). The array is writable, so you could do things like
strcpy( s, "world!" ); /* This should work, and s[] now contains "world!\0" */
However, the second declaration defines t as a "pointer to char" and initializes it to point to the (anonymous) string "world!\0", which the compiler is entitled to put anywhere, including in the text (code) segment of your program, which is read-only. Therefore, trying to modify this will give you an error.
ASKER
You mean s is pointing to fixed memory location but writeable. And t can point to any location but readonly?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I think you mean to swap s and t in your last 2 sentences above?
//The last 2 sentences are correct.
char s[] = "Hello ";
char *t = "world!";
s=t; // error
t=s; // valid;
char s[] = "Hello ";
char *t = "world!";
s=t; // error
t=s; // valid;
ASKER
What you are saying is somewhat contradicts with what historychef is saying.
Where do you see a contradiction?
ASKER
In other words does below correct??
char s[] means char * const s i.e. constant pointer to char
char *t means char const *t i. e. pointer to constant char
at least as far as behaviour is concerned??
char s[] means char * const s i.e. constant pointer to char
char *t means char const *t i. e. pointer to constant char
at least as far as behaviour is concerned??
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for detailed approach. Appreciate that.