所有答案都高度赞赏,以及所有用于澄清这些事情的人 - 非常感谢。
我正在学习C,刚刚完成了有关指针的章节。在这本书中,我给了一个示例代码,这使我真的很困惑。
示例代码的一部分:
...
1 char *inp_file = "";
2 char *out_file = "";
3 char ch;
4
5 while ( ( ch = getopt( argc, argv, "i:o:" )) != EOF )
6 {
7 switch( ch )
8 {
9 case 'i':
10 inp_file = optarg;
11 break;
12 case 'o':
13 out_file = optarg;
14 break;
15
16 default:
17 fprintf( stderr, "Unknown option: '%s'/n", optarg );
18 return 2;
19 }
20 }
21
22 argc -= optind;
23 argv += optind;
...
我的理解是char *inp_file = ""
和char *out_file = ""
是指的指针字符串文字。
他们指的是在哪里?考虑到这是一个空的"
当它们存储在读取内存中时,如何更新它们(第10、13行)?
char *pointer;
与char *pointer = "";
相同?
此外,我尝试了此操作。
#include <stdio.h>
int main( int argc, char *argv[] )
{
char *msg = "Hello";
msg = "World";
printf("%sn", msg );// Prints 'World'
}
我100%肯定char *msg = "Hello";
是字符串文字的指针。
当它在中读取仅读取内存?
中时,为什么它会更新为'world'这是一个全新的重新分配还是什么?
我现在真的很困惑我对指针的了解。我在这里想念什么?
我的理解是
char *inp_file = ""
和char *out_file = ""
是字符串文字的指针。
是的,他们是。
他们指的是在哪里?
他们指向一个空字符串字面。
char *pointer;
与char *pointer = "";
相同吗?
否。char *pointer;
是一个非初始化的指针,而char *pointer = "";
是初始化的指针。""
是类型const char[1]
具有元素' '
。
为什么在仅阅读内存中更新为
"World"
?
char *msg = "Hello";
等于
char const *msg = "Hello";
这意味着字符串字面的msg
点不得修改,但该约束在字符串字面上,而不是指向字符串字面的指针。msg
可以修改。
这是一个全新的重新分配还是什么?
msg = "World";
是指向指针msg
的新字符串的分配。
实际上有两件事。首先,有字符串文字。您创建了一个零长度的字符串""
,该字符串仍然是nul终止的,因为所有c字符串都是nul终止的 - 这就是您知道终点的方式。
因此,您有一个看起来像这样的内存:
Memory loc'n: Contents
BASE+0x0000: # start of string
BASE+0x0000: ' ' # end of string
也就是说,一个包含"无字符"的内存块,然后是尾随的nul字节来标记字符串的末端。
通常认为数据是"恒定的"。它可能会或不可存储在"恒定数据"中。这取决于链接器,操作系统等
但是,只是"常数字符串"。您的代码有第二部分:
char *inp_file = "";
您已将指针宣布为常数字符串字面。该指针是一个指针大小的对象(如果有32位地址空间,则为4个bytes,如果您有64位地址空间,则有8个bytes,如果您有不同的或混合的地址空间,则有些其他尺寸)并包含常数字符串文字的第一个字节的内存地址。
Memory loc'n: Contents
PTR_BASE+0x0000: (BASE+0x0000)
PTR_BASE+0x0008: ...
由于您在任何功能之外声明了inp_file
,因此被认为具有文件范围。A 文件范围初始化变量存储在数据段中(此处有关内存布局的更多信息)。(请注意,非初始化的变量可以存储在零段>或>非专业化段,取决于架构。)
另一方面,再次根据体系结构和平台,文件范围常数可以存储在数据段或或中,/strong>单独的常数段或包含程序代码的相同的段。
因此,您有两个内存位置,可能在不同的程序段中。第一个是您创建的"文字字符串" ""
。第二个是您声明的指针变量inp_file
。指针在加载时间用文字字符串的地址初始化。
您的程序运行后,您(可能)执行代码:
inp_file = optarg;
导致指针变量更改其值。现在,它没有指向您首先创建的文字字符串,而是指向由getopt
库确定的字符串。这可能在argv
区域中的某个地方,但是它可能位于堆上的strdup
ED块中(因为您不知道getopt
的工作原理以及在各种系统上的作用)。
请注意:回到当天,覆盖用作初始值的"恒定"字符串实际上是可能的,而且很普遍。您可能会发现仍然可以执行此操作的旧程序。Modern C对劝阻这一点非常积极,但大多数代码是旧版代码。; - )
您不更新"hello"
,您将msg
设置为指向另一个字符串,"World"
-它可能会或可能无法使用strcpy(msg, "World")
(取决于系统设置),但绝对是未定义的行为,所以不要编写执行此操作的代码)。
为了显示此信息,您可以在msg = "World";
行的两侧添加printf("Before: %pn", (void*)msg);
和printf("After: %pn", (void*)msg);
。