char* line = (char*) malloc(MAX_LINE_LEN);
这是一种糟糕的风格;您不需要malloc
在 C 中进行转换。让我们将其分为两部分,因为这样更容易描述和比较:
char *line;
声明一个指向名为 的 char 的指针line
。您可以将其分配为指向一个对象(或什么都没有)。sizeof
一个对象是它的类型的大小,所以是sizeof (line)
,sizeof (char *)
它因系统而异。&line
是 a 的地址char *
,其类型为char **
(指向 char 指针的指针)。它的存储时间取决于它的声明位置:
如果它在任何函数之外声明,则它具有静态存储持续时间,该持续时间持续到程序的生命周期。具有静态存储持续时间的对象被初始化为0
,除非存在显式初始化(例如在您的情况下)。0
是 a ,表示如果在没有初始化程序的函数之外声明null pointer constant
此对象,则该对象将不指向任何内容。
如果它是在代码块内声明的,它具有自动存储持续时间,持续到执行到达该代码块的末尾。具有自动存储持续时间的对象必须在使用之前显式初始化或分配,因为否则它们的值是不确定的。
您的初始化为其分配了一个值,因此无论如何它都不会开始不确定。malloc
返回指向具有动态存储持续时间的对象的指针,这意味着指针指向的对象将持续存在,直到它被显式free
d。
把它 line
想象成邮件信封上的邮政编码;您可以在其中写一些东西,这些东西将指示您可以找到对象(和人)的位置。邮政编码不会告诉您有关物体(或人)的大小的任何信息。
char line[MAX_LINE_LEN];
MAX_LINE_LEN
这声明了一个字符数组。
类型为char[MAX_LINE_SIZE]
,因此大小为sizeof (char[MAX_LINE_SIZE])
,如您所见,由指定的元素数量反映出来。&line
在这种情况下,地址是 a(指向字符char (*)[MAX_LINE_SIZE]
数组的指针)。MAX_LINE_SIZE
这个不能像上面那样重新分配,所以它与我们的邮政编码示例不同。当在编译器需要指针的地方使用数组时,数组将被隐式转换为指向第一个元素的指针。例如,让我们考虑:
strcpy(line, "Hello, world!");
函数原型char *strcpy(char *restrict s1, const char *restrict s2);
告诉我们它strcpy
接受两个char *
(指向 char 的指针)参数。在示例中,一个参数是 a char[MAX_LINE_LEN]
,另一个是 a char[14]
。两者都转换为char *
.
这个数组到指针的转换解释了为什么char *line; line = "hello";
是有效的,而char line[MAX_LINE_LEN]; line = "hello";
不是。您不能更改转换产生的指针。
我知道前者是指针,后者是数组,但系统如何分辨?
如前所述,当在需要指针的地方使用数组表达式时,它会转换为指针表达式。例如,array
inarray[x]
转换为pointer
in pointer[x]
。你在问什么?为什么它需要知道数组和指针之间的区别?
我认为一个数组存储在其他地方,当它超出范围时系统会自动释放它的内存,
是的。我之前解释了不同的存储持续时间。
当您处理指针时不会发生这种情况,因此您必须自己删除它。我错了吗?
是的。您将指针的概念与存储持续时间的概念混淆了。int *p = malloc(sizeof *p);
p 被初始化为指向int
具有动态存储持续时间的 a。在被调用int
之前不会被销毁。free(p);
但是,下面的两个变量都具有自动存储持续时间,因为它们是在 中声明的main
,没有任何限定符,例如static
. p
指向i
; p
是一个指针。不要free
p,因为它不指向具有动态存储持续时间的对象。free
仅定义为销毁具有动态存储持续时间的对象。
int main(void) {
int i = 42;
int *p = &i;
}