Home > Software engineering >  Why can't you change characters using pointers?
Why can't you change characters using pointers?

Time:11-10

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 ROM
  • char s[] = "Hello world!"; — local, mutable array initialized from ROM

That’s it!

  • Related