7

In C99 a string is typically initialized by using the char* data type since there is no primitive "string" data type. This effectively creates an array of chars by storing the address of the first char in the variable:

FILE* out = fopen("out.txt", "w");
char* s = argv[1];
fwrite(s, 12, 1, out);
fclose(out);
//successfully prints out 12 characters from argv[1] as a consecutive string.

How does the compiler know that char* s is a string and not just the address of a singular char? If I use int* it will only allow one int, not an array of them. Why the difference?

My main focus is understanding how pointers, referencing and de-referencing work, but the whole char* keeps messing with my head.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
jnitram78
  • 91
  • 4
  • The compiler does not know that `char* s` is a string. `char* s` is a pointer to char, as the same as `int* s` is a pointer to int. We can get the whole string as long as we reached a final '\0'. – Will Jul 01 '15 at 05:56
  • 1
    "If I use int* it will only allow one int". That's not true. In C `int*` can be used as an array. – kaylum Jul 01 '15 at 05:56
  • @AlanAu: No, pointers cannot be used as arrays. – Keith Thompson Jul 01 '15 at 05:58
  • 3
    The relationship between arrays and pointers can be confusing. Section 6 of the [comp.lang.c FAQ](http://www.c-faq.com/) does a very good job of explaining it. – Keith Thompson Jul 01 '15 at 06:00
  • @KeithThompson Perhaps we are referring to different things. `int *i_array = malloc(10*sizeof int); i_array[1] = 1;`? – kaylum Jul 01 '15 at 06:01
  • 1
    @AlanAu: `i_array` is a pointer, not an array. The prefix of the `[]` operator must be a pointer (which is often the result of the implicit conversion of an array). (Actually `[]` is commutative, but that's beside the point.) – Keith Thompson Jul 01 '15 at 06:11
  • declaring some variable `char *variable` does not automatically declares an array of characters, it only declares a pointer (a pointer and an array are different things) You must care on this!!! `string` type is not primitive even in C++. You can construct it as a C++ `class` and let it behave like it does. – Luis Colorado Jul 02 '15 at 08:24

3 Answers3

16

How does the compiler know that char* s is a string and not just the address of a singular char?

It doesn't. As far as "the compiler" is concerned, char* s is a pointer to char.

On the other hand, there are many library functions that assume that a char* points to an element of a null-terminated sequence of char (see for example strlen, strcmp etc.).

Note that fwrite does not make this assumption. It requires that you tell it how many bytes you want to write (and that this number doesn't take you beyond the bounds of the buffer pointed at by the first argument.)

If I use int* it will only allow one int, not an array of them. Why the difference?

That is incorrect. The C language does not have a special case for char*. An int* can also point to an element of an array of int. In fact, you could write a library that uses 0 or another sentinel value to indicate the end of a sequence of int, and use it much in the same was as char* are used by convention.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
7

In your code

fwrite(s, 12, 1, out);

is equivalent to writing

write 12 elements of size 1 byte, location starting from address s to the file pointed by out.

Here. a char is of one byte exactly, so you get the desired output.

How does the compiler know that char* s is a string and not just the address of a singular char?

Well, it does not (and does not need to). You asked to (read from s and) write 12 bytes, so it will do that. If the memory is inaccessible, that's a programming mistake. fwrite() itself won't handle that.

Beware:

  • If s is not allocated memory to be accessed upto s[11] (technically), it will be undefined behaviour. It's upto the programmer to pass the valid values as argument.

In case of int, the size is 4 bytes (usually, on 32 bit system) and printing byte-by-byte won't give you the desired result.

In that case, you need to make use of fprintf() to print formatted output.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

Compiler won't have any idea other than char* is an address of a character. We can make it read the characters following by incrementing the address of the first character. The case is similar to any pointer int*,long* etc., compiler just treat a pointer as something points to an address of its type.

Raams
  • 167
  • 1
  • 7