我试图更深入地研究以下行:
char* filename="file.txt";
当我们使用 fopen()
时我会这样做;
我的问题是:
filename
应该保存一个字符的地址(在 core2Duo 中为 36 位)。为什么我们要在其中放入“字符串”?为什么编译器不会生成错误,因为您可能存储了一个永远不存在的地址?
最佳答案
filename is supposed to hold an address of a character (36 bits in core2Duo), why we are putting a 'string' in it ?
表达式char* filename="file.txt";
是一个有效的表达式。原因是 C 中字符串文字的类型是 char[N]
很容易衰变成 char*
,和char[N]
和char*
是兼容的。因此,您可以将字符串地址分配给 char*
指针变量就像您在此表达式中所做的那样。
Why the compiler would not generate an error since you might be storing an address which can never exist?
请阅读以下三点:
- 它是一个有效的地址:
否,在表达式 char* filename="file.txt";
中, filename
被分配了一个有效的地址。从概念上讲,它类似于(假设地址以 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.
并且它不会给出任何错误或警告:尝试下面的代码示例:
示例 1:
#include<stdio.h>
int main(int argc, char **argv){
char* filename = "filename.txt";
printf("%s", filename);
return 0;
}
编译:
:~$ gcc y.c -Wall -pedantic
~$ ./a.out
filename.txt
没有错误和警告,编译和执行完美。
关于您对我的回答的评论:
C
中的字符串数据结构有点复杂,然后是简单的值变量,例如 int
, char
, float
.
对于基本数据类型:
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.
但是对于字符串,当你这样做时:
char* filename = "filename.txt";
那么你实际上是在分配字符串"filename.txt"
的地址到 char* 指针变量 filename
。
如果你这样做:
char filename[] = "filename.txt";
// ^ notice [] in declaration
然后您将分配字符串“filename.txt”;到一个字符数组 filename[]
,这里filename
类型是char[]
。
要了解两个声明中的更多尊重,请阅读:What does sizeof(&arr) return?
字符串文字可能会在您使用它的上下文中为您提供值或地址依赖性。例如尝试:printf(" address: %p, value: %s", "Hello", "Hello");
- 编译器不验证地址,而是检查语法。
编译器不负责验证地址是否合法。编译器移植代码并检查语法错误(例如不可编译的类型不匹配)。假设如果您将假地址分配给指针,它不会给您警告(如果您正确键入强制转换地址)。考虑下面的例子:
示例 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;
}
编译:
$ gcc y.c -Wall -pedantic
并且它不会产生任何错误或警告。因为从语法上来说,一切都很好并且有效。
(而 ptr
分配了一个可能不存在的虚假地址)。
- 无效地址会导致运行时出现未定义的行为
好吧,编译 example-2 代码即可,其中 ptr
被分配了一个假地址,即使使用坚持检查标志选项,编译器也不会生成任何错误/警告:-Wall -pedantic
。
但是执行这段代码是错误的。它尝试访问分配给 ptr
的内存地址在 printf 语句中,程序将表现异常(在不同的执行实例中)。在 C
-语言标准称为:Undefined behavior 。
当您执行此代码时,操作系统(而不是编译器)检测到进程对内存权限的侵犯 - 对有效内存的无效访问给出:SIGSEGV 对无效地址的访问给出:SIGBUS。这可能会导致进程终止/崩溃并出现一些段错误和 coredump 。
要了解并了解访问非法内存时会发生什么,请阅读:strcat() implementation works but causes a core dump at the end .
关于c - 为什么我们将字符串存储在字符指针中,例如 fopen(); 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17627394/