Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is an array's dimension part of its type?

Tags:

c++

arrays

c++11

While reading the C++ Primer book, I came across this statement: "The number of elements in an array is part of the array's type." So I wanted to find out using the following code:

#include<iostream>

int main()
{
    char Array1[]{'H', 'e', 'l', 'p'};
    char Array2[]{'P', 'l', 'e', 'a', 's', 'e'};

    std::cout<<typeid(Array1).name()<<std::endl;        //prints  A4_c
    std::cout<<typeid(Array2).name()<<std::endl;        //prints  A6_c

    return 0;
}

And interestingly the result of typeid on the two arrays showed they are somehow different.

  • What's going on behind the scenes?
  • Why is it necessary to for array's to have a type that includes its size? Is it just because its size should not change?
  • How will this affect comparing arrays?

Just want to be able to deeply understand the concept.

like image 871
octopus Avatar asked Nov 21 '19 14:11

octopus


People also ask

What determines the dimensions of the array?

The number of dimensions an array has is called its rank. You can use the Rank property to determine how many dimensions an array has.

What is an array and its types in C?

Array in C can be defined as a method of clubbing multiple entities of similar type into a larger group. These entities or elements can be of int, float, char, or double data type or can be of user-defined data types too like structures.

What is the purpose of an array in programming?

In coding and programming, an array is a collection of items, or data, stored in contiguous memory locations, also known as database systems . The purpose of an array is to store multiple pieces of data of the same type together.

Why is an array called a data structure?

Arrays are classified as Homogeneous Data Structures because they store elements of the same type. They can store numbers, strings, boolean values (true and false), characters, objects, and so on. But once you define the type of values that your array will store, all its elements must be of that same type.


2 Answers

What's going on behind the scenes?

A non dynamically-allocated is, by definition, a fixed-size container of homogeneous elements. An array of N elements of type T is laid out in memory as a contiguous sequence of N objects of type T.


Why is it necessary to for array's to have a type that includes it's size?

I do not believe it is "necessary" for an array's type to include it's size - as a matter of fact, you can use a pointer to refer to a contiguous sequence of T objects. Such pointer would lose size information about the array.

It is, however, a useful thing to have. It improves type safety, and encodes useful information at compile-time that can be used in multiple ways. As an example, you can use references-to-arrays to overload on arrays of different sizes

void foo(int(&array)[4]) { /* ... */ }
void foo(int(&array)[8]) { /* ... */ }

or to figure out the size of an array as a constant expression

template <typename T, std::size_t N>
constexpr auto sizeOf(const T(&array)[N]) { return N; }

How will this affect comparing arrays?

It doesn't, really.

You cannot compare C-style arrays in the same way you would compare two numbers (e.g. int objects). You would have to write some sort of lexicographical comparison, and decide what it means for collections of different sizes. std::vector<T> provides that, and the same logic can be applied to arrays.


Bonus: C++11 and above provides std::array, which is a wrapper around a C-style array with a container-like interface. It should be preferred to C-style arrays as it is more consistent with other containers (e.g. std::vector<T>), and also supports lexicographical comparisons out of the box.

like image 147
Vittorio Romeo Avatar answered Sep 19 '22 05:09

Vittorio Romeo


The amount of space that is allocated to an object when you create it depends entirely on its type. The allocation I'm talking about isn't allocations from new or malloc, but the space that is allocated so that you can run your constructor and initialize your object.

If you have a struct defined as (for example)

struct A { char a, b; }; //sizeof(A) == 2, ie an A needs 2 bytes of space

Then when you construct the object:

A a{'a', 'b'};

You can think of the process of constructing the object as a process:

  • Allocate 2 bytes of space (on the stack, but where doesn't matter for this example)
  • Run object's constructor (in this case copy 'a' and 'b' to the object)

It's important to note that the 2 bytes of space needed is entirely determined by the type of the object, the arguments to the function don't matter. So, for an array the process is the same, except now the amount of space needed depends on the number of elements in the array.

char a[] = {'a'}; //need space for 1 element
char b[] = {'a', 'b', 'c', 'd', 'e'}; //need space for 5 elements

So the types of a and b must reflect the fact that a needs enough space for 1 char and b needs enough space for 5 chars. That does mean that the size of these arrays cannot suddenly change, once a 5-element array is created it is always a 5-element array. In order to have "array"-like objects where the size can vary, you need dynamic memory allocation, which your book should be cover at some point.

like image 26
SirGuy Avatar answered Sep 21 '22 05:09

SirGuy