recently I got a copy of the C Programming Language Book. On page 95 there is an implementation of the strcpy function.
void strcopy(char *s, char *t) {
while(*s = *t )
;
}
int main(int argc, char *argv[]) {
char *hello = "hello";
char *world = "world";
strcopy(hello, world);
return 0;
}
i tried to implement it myself, but after (successfully) compiling with
gcc -o c_lang c_programming_lang_exercises.c
and trying running it with
./c_lang
I get the following error message:
zsh: bus error
I tried it with different implementations, but somehow this does not work for me.
Maybe someone has an idea why?
Thank you for your help :)
Edit: For my own understanding, please correct me if im wrong. In the function call "strcopy(hello, world);" i pass the value of the pointers itself here, so i call the function with something like this: strcopy(0x123a4, 0x234859b). Now C doesnt sees this as variable, and therefore its value get copied and passed to the function. In the strcopy function itself i cant dereference it, because i just get the value of the pointers.
What i should do is to pass the address, the pointers refere to, so that i can dereference the values in the strcopy function and access the right memory address.
The other mistake was probably in the main function i declared char *hello = "hello"
that is as far as I understand it, called a string constant and is therefore not modifiable.
So, if my assumptions are correct, the following code should work:
void strcopy(char *s, char *t) {
//code goes here...
}
int main(int stringc, char *argv[]) {
char hello[] = "hello";
char world[] = "world";
strcopy(&hello, &world);
return 0;
}
And it works, but i get the following compiler warning:
incompatible pointer types passing 'char (*)[6]' to parameter of type 'char **' [-Wincompatible-pointer-types]
strcopy(&hello, &world);
CodePudding user response:
C makes a really bad concession when it comes to types, and this has to do with historical reasons.
In main()
, you declare your strings as:
char *hello = "hello";
What you should do is turn the warning levels waaaay up and recompile. The problem is that "hello"
is a string literal — it cannot be modified. It should be declared as:
const char *hello = "hello";
(Turning warnings up will tell you this.)
Consequently, you are trying to copy characters into read-only memory, which, on modern processors and with modern compilers, is not permitted — it produces an access violation. Zsh complains for you.
Instead, make sure you have write access to a local array that is copied from read-only memory:
char hello[] = "hello";
Yep, that makes a local, mutable array that is six characters long (five for the word “hello” plus one for the null-terminator) and automatically initialized from the read-only memory.
This is one of those subtle sticking points to declaring things in C that confuses beginners regularly:
const char * s = "Hello world!";
— pointer to ROMchar s[] = "Hello world!";
— local, mutable array initialized from ROM
That’s it!