0

I know for a fact that string contents of a pointer is not modifiable. But consider the code below. Does that mean cf has been changed to the type "char array" (whose content is modifiable).

#include <stdio.h>

int main()
{
  char line[100];
  char *cf;
  cf = line;  //cf (of type pointer-to-pointer-to-char) is converted?

  *cf = 's';
  *cf = 'g';
  printf("%c", *cf);
}

Below DOESN't work.

int main()
{
  char *cf;
  *cf = 's';
  *cf = 'g';

  printf("%c", *cf);
}
Gerhardh
  • 11,688
  • 4
  • 17
  • 39
Roy
  • 63
  • 8
  • You assign: `char *cf = something;` Assume the type of `something` is not `char *`. Does this mean that `cf` now suddenly changes its type to equal that of `something`, given that earlier you declared `char * cf`? – ForceBru Jul 12 '19 at 08:33

4 Answers4

3

In the first snippet, cf is not an array, but points to one. So you can use it to acess the array's values. You can even use array access syntax like cf[1].

In your second snippet, cf is still a char*. It's uninitialized, so assigning to the place it points to is undefined behavior.

You're just writing and reading one byte, so it might do as you expect... but it might also crash due to an access violation, cause data corruption because you changed memory that was used by something else, or something entirely different may happen.

Blaze
  • 16,736
  • 2
  • 25
  • 44
3

Does that mean cf has been changed to the type "char array"

No. The type of a variable never changes from the declared type, no matter what you assign to it.

The first snippet assigns a pointer to the first element of the array to cf. One says the array decays into a pointer.

Below DOESN't work.

Dereferencing an uninitialized pointer results in undefined behaviour. You haven't ensured that *cf points to somewhere appropriate, so you are attempting to writing to memory you shouldn't. Maybe you'll succeed. Maybe the program will be killed. Maybe weird things will start happening. In any case, it's something you must avoid.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • @if the type for `cf` (which i think is a pointer to the 1st element of the array `line`), how come I can modify `cf`'s content? Isn't it illegal to modify a string content of a pointer? Thanks. – Roy Jul 12 '19 at 09:15
  • Re "*if the type for `cf` (which i think is a pointer to the 1st element of the array line*", That's not a type, much less `cf`'s. – ikegami Jul 12 '19 at 09:16
  • 1
    Re "*how come I can modify `cf`'s content?*", Because that's what assignment does? – ikegami Jul 12 '19 at 09:17
  • Re "*Isn't it illegal to modify a string content of a pointer?*", There's no string involved -- a string is a NUL-terminated sequence of `char`-- and why would it be illegal to modify a sequence of characters? – ikegami Jul 12 '19 at 09:20
  • Re "*sorry, I meant cf's type is one of pointer...*". I know. "Pointer to the 1st element of the array line" doesn't describe a type; it describes a value. – ikegami Jul 12 '19 at 09:23
2

I know for a fact that string contents of a pointer is not modifiable.

That's only partially true...

A pointer is in the end just the address of some memory. A pointer of type char can point to some single character, to the beginning or even into the middle of some array or one past the end of such an array (well, but you need to assign a valid address to a pointer before using it – which is not the case in your main function: "doesn't work"). You can modify any such array via a pointer, provided the array itself is not const.

Exactly the same for C strings; actually, these are nothing more than an array stored somewhere in memory. Requirement to be able to interpret the data in this array as 'string' is that the last character part of the actual string data is a null-character (which doesn't necessarily have to be the last character in the entire array), and you can have a pointer to that array (char* or char const*).

Now there's the special case of string literals, i. e. any string you define with double quotes: "hello world". In reality, these are arrays, too, containing the the contents defined plus the terminating null character. These arrays are immutable albeit not being const.

Normally, they should be const (just as they are in C++), but string literals existed before const did – and for compatibility reasons, their type was retained as char* instead of char const* when the new keyword finally was introduced.

Still I recommend consistently assigning string literals only to const pointers to avoid undefined behaviour due to modified string literals.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • "*Exactly the same for C strings; actually, these are nothing more than a pointer to some array.*" this is misleading, to not say wrong. An array is not a pointer. So a C-string is not a pointer. And a pointer is not a C-string. – alk Jul 20 '19 at 12:04
1

In your first code part, there is an implicit conversion of an expression from an array type to a pointer type. As far as I know, when the compiler sees an array expression it converts the type of the expression(char array in your case) from "100-element array of char” to "pointer to char” and sets the value of the expression to the address of the first element of the array.

In your second code part, cf points to a random memory address or may be NULL, there is no guarantee. At this case, you are lucky since you are not in kernel-level. That is, you are trying to write data into a random place high probably. It’s known as UB.