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