2

Kernighan & Ritchie 2nd ed. says:

The correspondence between indexing and pointer arithmetic is very close. By definition, the value of a variable or expression of type array is the address of element zero of the array. Thus after the assignment
pa = &a[0];

pa and a have identical values. Since the name of an array is a synonym for the location of the initial element, the assignment pa=&a[0] can also be written as
pa = a;

If a and pa are identical, then why this code:

#include <stdio.h>

int main()
{
    char a[] = "hello";
    char *pa = a;
    printf("Array: %ld\n", sizeof(a));
    printf("Pointer: %ld\n", sizeof(pa));
}

Outputs this:

Array: 6
Pointer: 8

Reference to an authoritative source would be much appreciated.

Gill Bates
  • 14,330
  • 23
  • 70
  • 138

5 Answers5

3

Two objects can have the same address but their sizes can be different.

From the C Standard (6.5.3.4 The sizeof and alignof operators)

2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand....

Consider the following example

#include <stdio.h>

int main( void )
{
    struct A
    {
        char c;
        int x;
    } a;

    printf( "object a:\taddress - %p size - %zu\n",
            &a, sizeof( a ) );
    printf( "object a.c:\taddress - %p size - %zu\n",
            &a.c, sizeof( a.c ) );
}    

The program output is

object a:   address - 0x7fff164e16d0 size - 8
object a.c: address - 0x7fff164e16d0 size - 1

As it is seen the object a of type struct A and its data member c of type char have the same address but different sizes.

As for arrays then a pointer is an object that stores an address of other object. To store an address of other object it is enough to allocate for example 4 or 8 bytes of memory for the pointer depending on the used system.

As for arrays then they are named extents of memory. Arrays do not store addresses. They store their own elements (that of course can be pointers).

An array name used in expressions is converted to pointer to its first element.

According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

In this quote there is listed when an array is not converted to a pointer to its first element. For example when an array is the operand of sizeof operator.

If to return to your program

int main()
{
    char a[] = "hello";
    char *pa = a;
    printf("Array: %ld\n", sizeof(a));
    printf("Pointer: %ld\n", sizeof(pa));
}

then in this statement

    char a[] = "hello";

string literal "Hello" that has type char[6] is not converted to a pointer. However in this statement

    char *pa = a;

array a is converted to pointer to its first element.

And in this statement

    printf("Array: %ld\n", sizeof(a));

array a is not converted to a pointer because it is the operand of the sizeof operator.

However if you used an expression in the sizeof operator for example like this

sizeof( a + 0 )

then you would get a pointer and correspondingly the sizeof would return the size of the pointer instead of the size of the array

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

They do indeed have identical values. But that doesn't mean they are the same thing.

a is still a fixed-sized array. pa is still a pointer.

sizeof is one operator that recognises this difference.

Your array has 6 elements of size char (sizeof(char) is defined by the standard to be 1). (The 6th element is the string null terminator).

sizeof(char*) is 8 on your system. It's probably 64 bit.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Detail: "They do indeed have identical values" Disagree that `pa` and `a` have the same value. IMO, `a[]` has a 6 `char` _value_. In the context of `char *pa = a;`, the expression `a` is converted to a `char *` with a value of of the initial element of `a` and that is assigned to `pa`. Yet `a` does not have the value of a pointer. – chux - Reinstate Monica Aug 19 '15 at 16:23
  • I know what you're saying, but I say the *values* are equal though the *types* are different. – Bathsheba Aug 19 '15 at 16:27
2

Arrays are not pointers. The array name decays to a pointer to its first element in many cases, but sizeof is one of the few exceptions.

C11 §6.3.2.1 Lvalues, arrays, and function designators

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • `_Alignof` should be out of the exception list! – haccks Aug 19 '15 at 15:46
  • @haccks Source? I'm quoting from the draft of the standard. – Yu Hao Aug 19 '15 at 15:51
  • That's a **bug** in the standard. See what C11 standard says: *The `_Alignof` operator yields the alignment requirement of its operand type. The operand is not evaluated and the result is an integer constant. **When applied to an array type, the result is the alignment requirement of the element type**.* (6.5.3.4 p3). – haccks Aug 19 '15 at 16:12
1

a and pa are not identical. Always remember: Arrays are not pointers. When used in an expression arrays are converted to pointer to its first element with some exception including as an operand of sizeof operator.
sizeof(a) will give the size of array while sizeof(pa) will give the size of pointer.

haccks
  • 104,019
  • 25
  • 176
  • 264
1
 char a[] = "hello";
 char *pa = a;

Here sizeof(a) will give size of array a . And sizeof(pa) will give size of pointer pa.Both are different .

Also as in function arguments array decays to pointer but this one is exception along with &.

Also while printing type size_t you should use specifier %zu (as specified in ANSI C99).

ameyCU
  • 16,489
  • 2
  • 26
  • 41