在C—中使用#定义值作为函数参数;它为什么有效?
在我上一个个人C项目中,我玩了一些文件。我尝试过的一件事是使用在C—中使用#定义值作为函数参数;它为什么有效?,c,file,fopen,C,File,Fopen,在我上一个个人C项目中,我玩了一些文件。我尝试过的一件事是使用#define值作为参数。最后是一段代码片段,以便您了解我的意思 我的问题是:它为什么起作用?数据存储在哪里?它符合ANSI C标准吗 #include <stdio.h> #define FILE_NAME "test.txt" void open_file(FILE**, char*); int main(int argc, char *argv[]) { FILE* file; open_file(&
#define
值作为参数。最后是一段代码片段,以便您了解我的意思
我的问题是:它为什么起作用?数据存储在哪里?它符合ANSI C标准吗
#include <stdio.h>
#define FILE_NAME "test.txt"
void open_file(FILE**, char*);
int main(int argc, char *argv[])
{
FILE* file;
open_file(&file, FILE_NAME);
return 0;
}
void open_file(FILE** file, char* filename)
{
*(file)=fopen(filename, "r");
}
#包括
#定义文件名“test.txt”
作废打开的文件(文件**,字符*);
int main(int argc,char*argv[])
{
文件*文件;
打开文件(&文件,文件名);
返回0;
}
作废打开文件(文件**文件,字符*文件名)
{
*(文件)=fopen(文件名,“r”);
}
为什么我可以将文本作为参数而不是存储文件名的字符数组?预处理器将代码扩展为
打开的文件(&file,“test.txt”)代码>
“test.txt”
是字符串文本。编译器将其嵌入到二进制可执行文件中。当您加载程序时,它会加载到内存中
让我们分析一下这个简单的例子:
#include <stdio.h>
int main(int argc, char **argv) {
printf("hello, wolrd!\n");
return 0;
}
如您所见,字符串被放置在.rodata
-只读数据部分。您可以获取该字符串的内存地址并尝试访问它:
#include <stdio.h>
int main(int argc, char **argv) {
const char *s1 = "hello, world!\n"; // both strings are identical
char *s2 = "hello, world!\n";
printf(s1); // Read-only access - OK
s2[0] = 'x'; // Write to .rodata - SEGFAULT (crash) here
return 0; // we never reach here
}
#包括
int main(int argc,字符**argv){
const char*s1=“你好,世界!\n”;//两个字符串完全相同
char*s2=“你好,世界!\n”;
printf(s1);//只读访问-确定
s2[0]=“x”;//在此处写入.rodata-SEGFAULT(崩溃)
返回0;//我们永远无法到达这里
}
顺便说一句,指针s1
和s2
应该相同。编译器能够优化相同的字符串并只存储一次。我不理解这个问题。您定义了一个被预处理器替换的宏,因此您的调用实际上是open_文件(&file,“test.txt”)代码>-您不想这样做吗?预期的行为是什么?实际的行为是什么?一切都很好。我希望它以这种方式工作,但我想知道为什么我可以使用字符串作为参数,而不是包含文件名的char数组。我还想知道字符串存储在哪里(可能是堆栈?)。最后是符合ANSI-C的参数类型?“为什么我可以用字符串作为参数而不是字符数组”字符串是字符数组,我知道。我指的是文本。srythx,这就是我想知道的。所以它存储在内存中,但我没有变量名来访问它,除非我声明一个pionter并用这个字符串初始化它。现在有趣的是,字符串是只读的,但是您可以使用指向非常量字符串的指针来访问它,从而触发崩溃。这是使用s2
字符串显示的。这不是一个bug,它是C语言的一个特性。有人开玩笑说C是“高级汇编”——你可以看到原因。链接到以获取有关字符串文字的更多信息(仅用于完成)
#include <stdio.h>
int main(int argc, char **argv) {
const char *s1 = "hello, world!\n"; // both strings are identical
char *s2 = "hello, world!\n";
printf(s1); // Read-only access - OK
s2[0] = 'x'; // Write to .rodata - SEGFAULT (crash) here
return 0; // we never reach here
}