int * vs int [N] vs int (*)[N] in functions parameters. Which one do you think is better?

When programming in C (or C++) there are three different ways to specify the parameter in a function that takes an array.

Here is an example (implementing std::accumulate from C++ in C) that shows you what I mean.

I can write it like this:

int accumulate(int n, int *array)
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += array[i];
    }
    return sum;
}

This can also be written to this (which means the very same thing):

int accumulate(int n, int array[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += array[i];
    }
    return sum;
}

I can also write it like this:

int accumulate(int n, int (*array)[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += (*array)[i];
    }
    return sum;
}

All these options are very similar and generate the same executable code but they have a slight difference which is how the caller passes the arguments.

This is how the first two options gets called:

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%dn", accumulate(ARRAY_LENGTH(a), a));
    return 0;
}

This is how the thrid option gets called:

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%dn", accumulate(ARRAY_LENGTH(a), &a));
    return 0;
}

Note that the third option requires to user to explicitly specify the address of a
with &a. The first two options does not require this because arrays implicitly gets converted into pointers to the same type in C.

I have always preferred the third approach.

This is why:

  • It is more consistent with how other types are passed by pointers.

    int draw_point(struct point *p);
    
    int main()
    {
        struct point p = {3, 4};
        draw_point(&p); // Here is the 'address of' operator required.
    }
    
  • It makes it possible to use macros like ARRAY_LENGTH to get the amount of elements in the array.

    #include <stdio.h>
    #define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0]))
    
    void this_works(int (*array)[10])
    {
        /* This works! */
        printf("%dn", ARRAY_LENGTH(*array));
    }
    
    void this_is_invalid_and_dangerous(int array[10])
    {
        /* This does NOT work because `array` is actually a pointer. */
        printf("%dn", ARRAY_LENGTH(array));
    }
    

The only advantage I see with int array[] (and int *array) is that you get to write array[X] instead of (*array)[X] when you wish to grab an index.

What are your professional thoughts on this? Which approach do you think is better and why? Do you ever mix the two? If so when do you choose what?

Like I said have I always preferred using int (*array)[N] but I see that the other two approaches are quite common as well.

4

In practice, you’ll see

int accumulate( int n, int *array)

most often. It’s the most flexible (it can handle arrays of different sizes) and most closely reflects what’s happening under the hood.

You won’t see

int accumulate( int (*array)[N] )

as often, since it assumes a specific array size (the size must be specified).

If your compiler supports variable-length array syntax, you could do

int accumulate( size_t n, int (*array)[n] )

but I don’t know how common that is.

7

In C, when the array notation is used for a function parameter, it is automatically transformed into a pointer declaration, so declaring parameter as int* array and int array[] are equivalent. I tend to use second one because it is more clear that function expects an array as an argument.

Declaring function parameter as int (*array)[] is not equivalent to previous two, it is transformed to int** and it should be used when value of the parameter itself could be changed in function, i.e. reallocation of the array.

4

You say that there are 3 ways in C and C++, but C++ actually makes a fourth available:

template<std::size_t n>
void arrayFunction(std::array<int,n> &array)
{ ...}

This has several advantages over the solutions you suggest:

  • The parameter for the size of the array will be automatically determined on use by the compiler, meaning you don’t have to specify it
  • The size is a compile time constant, meaning that the compiler can perform many optimizations that are impossible for the versions you suggest
  • It is impossible to specify an incorrect size, as the size is part of the type of the array

The first declaration also allows you write the function differently:

int accumulate(int n, int *array)
{
    int sum = 0;
    while (n-- > 0) sum += *array++;
    return sum;
}

so you don’t need the variable i.

Whatever’s idiomatic to the code base should be preferred, followed by whatever’s the easiest to understand, followed at some distance by whatever’s the most performant. The second declaration is the easiest to understand.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật