C中的数组和指针有什么区别?

时间:2013-04-27 10:02:06

标签: c arrays pointers memory-management

这个问题可能听起来很愚蠢,但我并不确定。我的意思是,有什么区别:

char* line = (char*) malloc(MAX_LINE_LEN);

char line[MAX_LINE_LEN];

到底是什么?我知道前者是一个指针而后者是一个数组,但系统如何区分呢?如何分配/存储内存?

另外,为什么可以删除line在声明为指针时占用的内存,而不是当它是数组时?我认为数组存储在其他地方,当系统超出范围时,系统会自动释放内存,这在处理指针时不会发生,所以你必须自己删除它。我错了吗?

4 个答案:

答案 0 :(得分:2)

char* line = (char*) malloc(MAX_LINE_LEN);

这种风格很差;您不需要在C中投射malloc。让我们将其分为两部分,因为它更容易描述和比较:

char *line;声明指向名为line的char的指针。您可以将其指定为指向对象(或不指向任何对象)。 sizeof对象是其类型的大小,因此sizeof (line)sizeof (char *),因系统而异。 &linechar *的地址,其类型为char **(指向char的指针)。它的存储持续时间取决于它的声明位置:

  • 如果它在任何函数之外声明,它具有静态存储持续时间,持续时间为程序的生命周期。具有静态存储持续时间的对象初始化为0,除非存在明确的初始化(例如在您的情况下)。 0null pointer constant,表示如果在没有初始化函数的情况下在函数外声明了此对象将指向 nothing

  • 如果它在代码块中声明,它具有自动存储持续时间,持续到执行到达该代码块的末尾。具有自动存储持续时间的对象必须在使用之前显式初始化或分配,因为它们的值不确定。

您的初始化为其分配了一个值,因此无论如何它都不会开始不确定。 malloc返回指向具有动态存储持续时间的对象的指针,这意味着指针指向的对象将持续存在,直到明确显示free d。

line视为邮件信封上的邮政编码;你可以在那里写一些东西,并且某些东西将指示你可以找到对象(和人)的位置。邮政编码不会告诉您有关对象(或人员)大小的任何信息。


char line[MAX_LINE_LEN];

这声明了一个MAX_LINE_LEN个字符数组。

  • 如果在任何函数之外声明,它具有静态存储持续时间,整个数组都是零填充。

  • 如果在函数或代码块中声明,它具有自动存储持续时间,并且数组中的值是不确定的;它们需要初始化(例如char line[MAX_LINE_SIZE] = { 0 };将初始化所有这些)或分配给(例如line[0] = '\0';将分配给数组的第一个元素),然后再使用它们。

类型为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 的指针)参数。在示例中,其中一个参数是char[MAX_LINE_LEN],另一个是char[14]。两者都转换为char *

此数组到指针转换解释了char *line; line = "hello";有效的原因,而char line[MAX_LINE_LEN]; line = "hello";则不然。您无法更改转换产生的指针。

  

我知道前者是指针而后者是数组,但怎么可能   系统分辨出来了吗?

如前所述,当数组表达式在预期指针的位置使用时,它将转换为指针表达式。例如,array中的array[x]转换为pointer中的pointer[x]。你在问什么?为什么需要知道数组和指针之间的区别?

  

我认为数组存储在其他地方和系统中   当它超出范围时自动解除分配内存,

是。我之前解释了不同的存储持续时间。

  

当您处理指针时不会发生这种情况   自己删除它。我错了吗?

是。您将指针的概念与存储持续时间的概念混淆了。 int *p = malloc(sizeof *p); p初始化为指向具有动态存储持续时间的int。在int被调用之前,free(p);不会被销毁。但是,下面的两个变量都具有自动存储持续时间,因为它们在main内声明,没有任何限定符,例如staticp指向i; p是一个指针。不要free p,因为它不指向具有动态存储持续时间的对象。 free仅定义为销毁具有动态存储持续时间的对象。

int main(void) {
    int i = 42;
    int *p = &i;
}

答案 1 :(得分:1)

char* line;

在堆栈上分配指针。当program counter超出本声明的范围时,它将自动释放。

line = (char*) malloc(MAX_LINE_LEN);

在堆上动态分配MAX_LINE_LEN个字节。确切地说,您应该以这种方式使用malloc

line = malloc(MAX_LINE_LEN * sizeof(char));

稍后您应该调用free(line)来释放此堆内存。

sizeof(line)将返回指针占用的字节数(通常为4或8个字节)。


char line[MAX_LINE_LEN];

在堆栈上分配MAX_LINE_LEN个字符。当program counter超出本声明的范围时,它将自动释放。

sizoef(line)将返回MAX_LINE_LEN * sizeof(char)个字节。

答案 2 :(得分:1)

理解这一点的最佳资源可能是comp.lang.c FAQ

务实地,区别在于sizeof运算符的效果。 sizeof(pointer)给出了指针的大小,而sizeof(array)给你......你猜对了。

作为函数参数传递时,数组名称会衰减为指向第一个元素的指针(丢失sizeof信息)。在正常表达式中,它表现为,好像它已衰减为指针,因为数组语法是根据等效指针操作定义的。 (实际上,早期的C编译器声明指针为identifier[]。)

A[X]
根据定义,

完全等同于

*(A + X)

需要注意的是,在A[X] AXeither one)中只有一个必须是指针或数组。

答案 3 :(得分:1)

答案就在那里,堆和堆栈问题。

数组,指针,局部变量是堆栈对象,堆对象使用malloc / free方法。

请查看What and where are the stack and heap?了解详情。

相关问题