为什么我们存储字符串中的字符指针,例如fopen()函数;? [英] why do we store string in a character pointer, e.g in fopen();?

查看:110
本文介绍了为什么我们存储字符串中的字符指针,例如fopen()函数;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想更深入的以下行:

 的char *文件名=file.txt的;

这我这样做的时候,我们使用 fopen()函数;

我的问题是:


  1. 文件名应该持有一个字符的地址(适用于酷睿2 36位)。为什么我们要放一个'字符串的呢?


  2. 为什么,因为你可能会被存储能够永远存在的地址,编译器会不会产生一个错误(S)?



解决方案

  

文件名应该持有一个字符的地址(酷睿2 36位),为什么我们都在上面放一个字符串?


这位前pression 的char *文件名=file.txt的; 是一个有效的前pression。原因是在C字符串的类型是的char [N] ,可以很容易衰变成的char * 的char [N] 的char * 是兼容的。因此,你可以字符串地址分配给的char * 像你这样的指针变量正在做这个前pression。


  

为什么编译器,因为你可能会被存储能够永远存在的地址,也不会产生错误?


请阅读以下三点:


  • 它是一个有效的地址:

没有,在EX pression 的char *文件名=file.txt的; 文件名被分配一个有效地址。它的概念是这样(假设地址以21开头):

  21名22 23 24 25 26 27 28 29
+ - + + + ------------------------------------
| 21 | ---> |'F'|'我'|'L'|'E'|'。'|'T'|'X'|'T'|'\\ 0'|
+ - + + + ------------------------------------文件名指向字符串,一个有效的地址。

和它不提供任何错误或警告:请尝试以下code例如:

例1:

 #包括LT&;&stdio.h中GT;
INT主(INT ARGC,字符** argv的){
    字符*文件名=FILENAME.TXT;
    的printf(%S,文件名);
    返回0;
}

编译:

 :〜$ GCC y.c -Wall -pedantic
〜$ ./a.out
FILENAME.TXT

没有错误,华林,其编制和执行完美。

关于你我的答案评论:

字符串在 C 是有点复杂的数据结构则简单值的变量,比如 INT 字符浮动

在基本数据类型的情况:


  INT I = 5;您正在分配值5,变量i
焦C ='A';您正在分配值'A'为char变量c。
浮动F = 5.5F;您正在分配值5.5F浮动变量f。


但对于字符串,当你这样做:

 的char *文件名=FILENAME.TXT;

然后,你实际上是指定字符串的地址FILENAME.TXT为char *指针变量文件名

而如果你做的:

 字符文件名[] =FILENAME.TXT;
      // ^通知,声明,[]

然后你要分配字符串FILENAME.TXT为CHAR 文件名[] ,这里文件名类型的char []

要了解在这两个声明的更多deferences阅读:什么的sizeof(安培; ARR )返回?

字符串文字可能会给你的价值或者你用什么情况下它的地址依赖性。例如尝试:的printf(地址:%P,值:%S,你好,你好);


  • 编译器不验证地址,但检查语法。

的编译器是不负责验证一个地址是合法的。编译器移植code和检查语法错误(例如不可编译的类型不匹配)。如果您分配一个假地址的指针它不会给你一个华林(如果你正确类型转换地址)假设。考虑下面的例子:

例2:

 #包括LT&;&stdio.h中GT;
INT主(INT ARGC,字符** argv的){
    字符*文件名=FILENAME.TXT;
    字符* PTR =(字符*)0x020202;
    的printf(%s%S \\ n,文件名,PTR);
    返回0;
}

编译:

  $ GCC y.c -Wall -pedantic

和它不会产生任何错误或华林。因为所有的语法是好的,有效的。结果
(而 PTR 分配可能不存在假地址)。


  • 无效的地址会导致在运行时不确定的行为

那么,它精编例2 code其中 PTR 分配AA假地址,而编译器不产生任何错误/即使有警示棒检查标志选项: -Wall -pedantic

但是,在执行此code是错误的。它试图访问的内存地址printf语句分配给 PTR ,程序将异常行为(不同的执行实例)。在 C -language标准其名为:未定义行为

在执行此code操作系统(而不是编译器)通过过程检测内存侵权问题 - 有效内存的无效访问,得出:SIGSEGV并获得无效的地址给:SIGBUS。这可能会导致终止进程/崩溃与一些段故障,并核心转储

要了解和知道,当你访问非法的内存读可以发生什么:<一href=\"http://stackoverflow.com/questions/16750998/strcat-implementation-works-but-causes-a-core-dump-at-the-end?answertab=votes#tab-top\">strcat()执行工作,但会导致核心转储在年底。

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?

解决方案

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.

这篇关于为什么我们存储字符串中的字符指针,例如fopen()函数;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆