-8

I am trying to look deeper in the following line:

char* filename="file.txt";    

This I do it when we use fopen();

My questions are:

  1. filename is supposed to hold an address of a character (36 bits in core2Duo). Why we are putting a 'string' in it?

  2. Why the compiler would not generate an error(s) since you might be storing an address which can never exist?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Manzer
  • 1
  • 2

4 Answers4

2

filename is supposed to hold an address of a character (36 bits in core2Duo), why we are putting a 'string' in it ?

The expression char* filename="file.txt"; is a valid expression. Reason is type of a string literals in C is char[N] that can easily decay into char*, and char[N] and char* are compatible. Hence you can assign string address to a char* pointer variable like you are doing in this expression.

Why the compiler would not generate an error since you might be storing an address which can never exist?

Please read below three points:

  • Its a valid address:

No, in the expression char* filename="file.txt";, filename is assigned a valid address. Its conceptually something like (assuming address starts with 21):

filename   21  22   23  24  25  26  27  28  29
+---+     +------------------------------------+
|21 |---> |'f'|'i'|'l'|'e'|'.'|'t'|'x'|'t'|'\0'|
+---+     +------------------------------------+

filename pointing to string, a valid address.

and It don't gives any error or warning: try below code example:

example-1:

#include<stdio.h>
int main(int argc, char **argv){
    char* filename = "filename.txt";
    printf("%s", filename);
    return 0;
}

Compile it:

:~$ gcc y.c  -Wall -pedantic 
~$ ./a.out 
filename.txt

No error and waring, its compiling and executing perfectly.

Regarding you comment to my answer:

Strings in C are bit complex data-structured then simple value variables like int, char, float.

In case of basic data-types:

int i = 5;  You are assigning value 5, to variable i
char c = 'A'; You are assigning value 'A' to char variable c. 
float f = 5.5f; You are assigning value 5.5f to float variable f.

But for strings, when you do:

  char* filename = "filename.txt"; 

Then you are actually assigning address of string "filename.txt" to char* pointer variable filename.

Whereas if you do:

  char filename[] = "filename.txt"; 
      //        ^ notice [] in declaration 

Then you are assigning string "filename.txt"; to an array of char filename[], here filename type is char[].

To learn about more deferences in both declarations read: What does sizeof(&arr) return?

A string literal may give you value or address dependences in what context you use it. for example try: printf(" address: %p, value: %s", "Hello", "Hello");

  • Compiler do not validates address but check syntax.

The compiler is not responsible to validate that a address is legal. Compiler transplants code and checks syntax errors(for example uncompilable type mismatch). Suppose if you assign a fake address to a pointer it won't give you a waring (if you correctly type casts address). Consider the below example:

example-2:

#include<stdio.h>
int main(int argc, char **argv){
    char* filename = "filename.txt";
    char* ptr = (char*)0x020202;
    printf("%s %s\n", filename, ptr);
    return 0;
}

Compile:

$ gcc y.c  -Wall -pedantic 

And it will not generates any error or waring. Because syntactically all is fine and valid.
(Whereas ptr assigned a fake address that may not exists).

  • Invalid address causes Undefined behavior at runtime

Well, its fine to compile example-2 code where ptr is assigned a a fake address, and compiler don't generates any error/warning even with stick checking flags options: -Wall -pedantic.

But executing this code is wrong. It try to access memory address assigning to ptr in printf statement, And the program will behave abnormally (at different executing instance). In C-Language standard its called: Undefined behavior.

When you executes this code OS (but not compiler) detects memory right violation by a process -- An invalid access to valid memory gives: SIGSEGV And access to an invalid address gives: SIGBUS. This may cause process terminate/crash with some segmentation fault and coredump.

To learn and know what can be happen when you access illegal memory read: strcat() implementation works but causes a core dump at the end.

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • Regarding your point: "Hence you can assign string address into char*" but I am assigning string and not string address. ande address should have &. – Manzer Jul 13 '13 at 06:35
  • @Manzer When you assign `"filename.txt"` to `filename` you are actually assigning address of string `"filename.txt"` to pointer. – Grijesh Chauhan Jul 13 '13 at 06:37
  • @Manzer In string bit complex data structure then simple then `char`,`int` when you do `i = 4` or `c = 'A'` you are assigning value but when you do `char* ptr = "hello"` then you are assigning address, but you assigning `char str[] = "hello";` you are assigning value. – Grijesh Chauhan Jul 13 '13 at 06:41
1

filename is supposed to hold an address of a character (36 bits in core2Duo), why we are putting a 'string' in it ?

The sad truth is that we aren't. We are putting a pointer to the first character of the string literal in it. The string "file.txt" is of type char[9], which, when assigned to a pointer, decays into char *. But you should be assigning it to a pointer to const char, since modifying it is illegal (results in undefined behavior). Read this.

Why the compiler would not generate an error since you might be storing an address which can never exist?

Excuse me, but what kind of never-existent address are you talking about? The address of the first character in the string literal is always explicitly valid!

(But even if it was -- the compiler knows very little, if any, about semantics. It simply cannot possibly always warn you if there's the possibility of using an invalid pointer. Sure, sometimes it can, but don't have high expectations.)

1

Please read some good C programming books, they explain what are pointers and arrays.

A string literal like "file.txt" is a char[] array (but you should think of it as const char[] because assigning inside string literals like "abc"[1]='D';is undefined behavior with bad taste, and gcc -Wall would warn you). Arrays can be (and usually are) understood as the pointer to their first cell (of index 0) - in other words arrays are decayed into pointers- So you can assign a string literal to a char pointer.

However, arrays are not pointers in C; for instance the sizeof some array is a suitable multiple of the size of each element, in particular sizeof("abcde") == 6 (because of the terminating null byte in every string literal). But the sizeof some pointer is independent of the size of the pointed zone, and on most systems all pointers have the same size, the size of the machine word.

You need to explicitly ask the compiler for all warnings (eg gcc -Wall on Linux) to get them.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 2
    First of all, `"file.txt"` is not `const char[]`, it's `char[9]`. Secondly arrays are not pointers. They are their own type. They can, however, decay to a pointer. – Wiz Jul 13 '13 at 05:59
  • 1
    I wrote "arrays can be understood as pointers" not "array are pointers", and you cannot write `"abc"[1] = 'D';` because it is a `const char[]` not a `char[]` – Basile Starynkevitch Jul 13 '13 at 06:00
  • @Wiz You may, however, want to talk to [this guy](http://stackoverflow.com/questions/17604952/convert-int-to-int-pointers-address#comment25624644_17604991) instead. –  Jul 13 '13 at 06:01
  • 1
    @BasileStarynkevitch You can certianly do "abc"[1] = 'D' because it's char[9] and NOT const char[]. However, the standard says that they are immutable and thus attempting to make that assignment invokes UB. Maybe you are confusing some other language with C (such as c++). See C11, 6.4.5 String literals, paragraph 6 for the type and paragraph 7 for the immutability behavior. – Wiz Jul 13 '13 at 06:04
  • Strictly speaking in `C` the type of string literal is `char[N]`. It is an array, not a pointer, but there's no `const` in the type. With gcc you can force the compiler to treat string litterals as 'const char *'. The option -Wwrite-strings will do that. While it is **not** standard `C`, it is really useful to make the code more robust. – Grijesh Chauhan Jul 13 '13 at 06:12
  • @Wiz in C++ its actually `const char[]`. – Grijesh Chauhan Jul 13 '13 at 06:35
  • @GrijeshChauhan But this is C, not C++. The semantics are clearly different. – Wiz Jul 13 '13 at 07:45
  • @Wiz Yes this is C not, C++. you are correct. I just given a comment because we confuse in C, C++. – Grijesh Chauhan Jul 13 '13 at 07:49
  • "arrays can be understood as pointers"" -- That's like "floats can be understood as ints". – Jim Balter Jul 13 '13 at 10:12
1
  1. Yes, it is holding an address, but it also happens to be that the address is followed by the next door neighbors' address, and their next door neighbors' address, etc. It is through this "string" of addresses that the value is actually found.
  2. The compiler should not generate an error because it could very well be that a "filename.txt" file will be created at some point during the future, and calls to fopen won't be evaluated until the program is actually run.
cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
  • I think address and strings are different. Addresses can be only fixed values.. while strings can be anything. So filename is expecting a valid physical address, but we are passing any arbitrary string of characters.. Would you mind putting some more explanation? Thanks in advance for that – Manzer Jul 13 '13 at 06:30
  • @Manzer Yes, it is holding an address, try to print: `printf(" address: %p, value: %s", "Hello", "Hello");` a string returns both what you wants depends. It depends what you wants out of this. – Grijesh Chauhan Jul 13 '13 at 07:28
  • @Manzer A string can be anything... at a series of sequential addresses. – cwallenpoole Jul 15 '13 at 13:24