Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of pointers on strings

I am really confused about the use of pointers on strings. It feels like they obey different rules. Consider the following code

  1. char *ptr = "apple";// perfectly valid here not when declaring afterwards like next
    
    ptr = "apple"; // shouldn't it be *ptr = "apple"
    
  2. Also printf() behaves differently -

    printf("%s", ptr) // Why should I send  the address instead of the value
    
  3. Also I came across the following code in a book

    char str[]="Quest";
    char *p="Quest";
    
    str++; // error, constant pointer can't change
    
    *str='Z'; // works, because pointer is not constant
    
    p++; // works, because pointer is not constant
    
    *p = 'M'; // error, because string is constant
    

I can't understand what is supposed to imply

Please help, I can't find any info anywhere else

like image 524
Gaurav Pant Avatar asked Dec 03 '22 12:12

Gaurav Pant


2 Answers

char *ptr;
ptr = "apple"; // shouldn't it be *ptr =      "apple"

No, because *ptr would be a char. So, you may write *ptr = 'a' but you can't write as you suggest.

printf("%s", ptr) // Why should I send  the address instead of the value

Because a string in C, is the address of a sequence of characters (char) terminated by zero (the null character aka \x0).

char str[] = "Quest";
char *p = "Quest";

str++; // error, constant pointer can't change

No, a pointer can perfectly change, but here, str is an array (which is slightly different from being a pointer). But, thus, it cannot deal with pointer arithmetic.

*str='Z'; // works, because pointer is not constant

No, it works because *str should be a char.

p++; // works, because pointer is not constant

No, it works because, this time, this is a pointer (not an array).

*p = 'M'; // error, because string is constant

Same as above, this is a char again, so it works because it is the right type and not because the string is 'constant'. And, as stated by Michael Walz in the comments, even though it might compile, it will produce an undefined behavior at runtime (most likely a crash with segfault) because the specification do not tell if the string pointed by *p is read-only or not (yet, it seems that most of the modern compilers implementation decide to make it in read-only). Which might produce a segfault.

For more information, refer to this SO question.

like image 168
perror Avatar answered Dec 11 '22 15:12

perror


1- I think you are making some confusion with variable declaration and definition. This line:

char *ptr = "apple";

declares a pointer to char and assigns the address of the first character "a" to the variable ptr. This line is equivalent to the following 2:

char* ptr;
ptr = "apple";

Now, string literals in C are read only. They are implicitly constant, it's the same as doing

const char* ptr;

So in fact, you can not change the contents of the location this pointer points to. Now, even if you could, the way you did it is wrong. Because ptr points to the location of the first character of the string, when you do *ptr you are accessing the contents of the first char of that string. So it expects a char, not a string. So it would be something like: *ptr = 'a';

2- Well, that's the way printf works. If you want to print a string with the %s specifier, it expects a pointer to that string, the address of the string's first character, not the string's value itself.

3- Now I'm going to comment your code.

str++; // error, constant pointer can't change

You are correct. Other people keep saying that arrays and pointers are slightly different, but they are not. Arrays are just an abstraction for the programmer to say that you're storing a sequence of values. At the assembly level, there is no difference at all. You could say that arrays are immutable pointers with mutable contents. An array stores the address of the first element of the sequence of values. You can change the contents of the array, but you can't change the address(the first element it points to).

*str='Z'; // works, because pointer is not constant

Now you're making some confusion. The pointer is actually constant, that is, you can not change the address it stores. But you can change the content the address points to, which is what the line above is doing. It's changing the first value of the sequence of values from the array.

p++; // works, because pointer is not constant

Correct. The pointer is not constant, although the content it points to is. You can change the address the pointer stores, but not the value it points at. String literals are mutable pointers to immutable strings.

*p = 'M'; // error, because string is constant

Correct, the string is immutable.

like image 22
savram Avatar answered Dec 11 '22 15:12

savram