What's the difference between an array and a pointer in C exactly?

This question may sound stupid but I'm not really sure about it. I mean, what's the difference between:

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

and

char line[MAX_LINE_LEN];

exactly? I know the former is a pointer and the latter is an array, but how can the system tell the difference? How is the memory allocated/stored?

Also, why can you delete the memory occupied by line when it's declared as a pointer, but not when it's an array? I think that an array is stored somewhere else and the system automatically deallocates its memory when it's out of scope, which doesn't happen when you are dealing with a pointer so you must delete it yourself. Am I wrong?


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

This is poor style; You don't need to cast malloc in C. Let's break this up into two sections, because it's easier to describe and compare that way:

char *line; declares a pointer to char named line . You can assign it to point to an object (or nothing). The sizeof an object is the size of it's type, so sizeof (line) is sizeof (char *) , which varies from system to system. &line is the address of a char * , which has the type char ** (pointer to pointer to char). It's storage duration depends upon where it is declared:

  • If it's declared outside of any function, it has static storage duration, which lasts for the lifetime of the program. Objects with static storage duration are initialised to 0 , unless an explicit initialisation exists (eg in your case). 0 is a null pointer constant , indicating that this object would point to nothing if it were declared outside of functions without an initialiser.

  • If it's declared inside of a block of code, it has automatic storage duration, which lasts until execution reaches the end of that block of code. Objects with automatic storage duration must be explicitly initialised or assigned to before they're used, because their value otherwise is indeterminate.

  • Your initialisation assigns a value to it, so it won't start off indeterminate regardless. malloc returns a pointer to an object that has dynamic storage duration, which means the object that the pointer points to persists until it is explicitly free d.

    Think of this line like the postcode on a mail envelope; You can write something in there, and that something will indicate a location where you can find objects (and people). The postcode doesn't tell you anything about the size of the objects (or people).


    char line[MAX_LINE_LEN];
    

    This declares an array of MAX_LINE_LEN chars.

  • If declared outside of any functions, it has static storage duration and the entire array is zero-filled.

  • If declared inside a function or block of code, it has automatic storage duration and the values in the array are indeterminate; They need to be initialised (eg char line[MAX_LINE_SIZE] = { 0 }; will initialise all of them) or assigned to (eg line[0] = ''; will assign to the first element of the array) before they're used.

  • The type is char[MAX_LINE_SIZE] , so the size will be sizeof (char[MAX_LINE_SIZE]) , reflected as you can see by the number of elements specified. The address of &line in this case is a char (*)[MAX_LINE_SIZE] (a pointer to an array of MAX_LINE_SIZE chars).

    This one can't be reassigned like the one above, so it differs from our postcode example. When an array is used in places where a compiler expects a pointer, the array will be implicitly converted to a pointer to the first element. For example, let us consider:

    strcpy(line, "Hello, world!");
    

    The function prototype char *strcpy(char *restrict s1, const char *restrict s2); , tells us that strcpy accepts two char * (pointer to char) arguments. In the example, one of the arguments is a char[MAX_LINE_LEN] , and the other is a char[14] . Both got converted to a char * .

    This array-to-pointer conversion explains why char *line; line = "hello"; char *line; line = "hello"; is valid, while char line[MAX_LINE_LEN]; line = "hello"; char line[MAX_LINE_LEN]; line = "hello"; isn't. You can't change the pointer that results from the conversion.

    I know the former is a pointer and the latter is an array, but how can the system tell the difference?

    As previously stated, an array expression is converted to a pointer expression when it's used in places where a pointer is expected. For example, array in array[x] is converted to pointer in pointer[x] . What are you asking? Why would it need to know the difference between an array and a pointer?

    I think that an array is stored somewhere else and the system automatically deallocates its memory when it's out of scope,

    Yes. I explained the different storage durations earlier.

    which doesn't happen when you are dealing with a pointer so you must delete it yourself. Am I wrong?

    Yes. You're confusing the concept of pointers with the concept of storage duration. int *p = malloc(sizeof *p); p is initialised to point to an int that has dynamic storage duration. That int won't be destroyed until free(p); is called. Both of the variables below, however, have automatic storage duration because they're declared within main , without any qualifiers such as static . p points to i ; p is a pointer. Don't free p, because it doesn't point to an object that has dynamic storage duration. free is only defined to destroy objects that have dynamic storage duration.

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

    char* line;
    

    Allocates pointer on a stack. It will be automatically freed when the program counter will go out of the scope of this declaration.

    line = (char*) malloc(MAX_LINE_LEN);
    

    Dynamically allocates MAX_LINE_LEN bytes on the heap. To be precise, you should use malloc in that way:

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

    Later you should call free(line) to release this heap memory.

    sizeof(line) will return number of bytes taken by the pointer (usually 4 or 8 bytes).


    char line[MAX_LINE_LEN];
    

    Allocates MAX_LINE_LEN chars on the stack. It will be automatically freed when the program counter will go out of the scope of this declaration.

    sizoef(line) will return MAX_LINE_LEN * sizeof(char) bytes.


    Probably the best resource for understanding this is the comp.lang.c FAQ.

    Pragmatically, the difference is in the effect of the sizeof operator. sizeof(pointer) gives you the size of a pointer, whereas sizeof(array) gives you ... you guessed it.

    When passed as a function argument, an array name decays into a pointer to the first element (losing the sizeof information). In a normal expression, it behaves as if it decayed to a pointer, because the array syntax is defined in terms of the equivalent pointer operations. (In fact early C compilers declared pointers with identifier[] .)

    A[X]
    

    is, by definition, exactly equivalent to

    *(A + X)
    

    with the caveat that in A[X] exactly one of A or X (either one) must be a pointer or array.

    链接地址: http://www.djcxy.com/p/79794.html

    上一篇: C ++指针节点

    下一篇: C中的数组和指针之间有什么区别?