Definition of array in c language - c

Definition of array is a collection of similar type of elements stored in adjacent locations.
Why is it not the collection of same elements stored in adjacent locations?

The authoritative quote, from the C11 standard:
An array type describes a contiguously allocated nonempty set of objects with a
particular member object type, called the element type. The element type shall be
complete whenever the array type is specified. Array types are characterized by their
element type and by the number of elements in the array. An array type is said to be
derived from its element type, and if its element type is T, the array type is sometimes
called ‘‘array of T’’.
Follow the emphasis (mine), it says about a (one) fixed type.
What you're expecting here, like
[...] collection of same elements [...]
may be misleading, as it may indicate that all the members has to be same type and value, which is not the case.
Rather, what is mentioned (whichever your source is)
similar type of elements
seems to do an appropriate job of conveying the actual stance.
TL;DR - All the member are of same type, the values can be same or different.

The same element means the same value, and that is not the right meaning.
A different way to say it would be: Definition of an array is a collection of elements *of the same type* stored in adjacent locations.

Related

Effective type of temporary object in C

This is a question related to defect report 452 of the C standard. Document N1888 provides further information about the original problem, but I cannot understand why it states the following:
The effective type rule from 6.5.p6 (the rule that describes what is the effective type of an object) does not seem to apply to an object with temporary lifetime resulting from a comma expression. As such, it does not seem to have an effective type. As such, type punning is seemingly allowed:
long func3() {
union u2 o3 = { .x=42 };
return (0, o3).y;
}
My question is what causes type punning to be legal if the object with temporary lifetime created by the expression (0, o3) does not have an effective type? I believe the effective type of that object would be relevant only if one would try to access its stored value using a different type, but I do not see how that is the case here.
I believe the effective type of that object would be relevant only if one would try to access its stored value using a different type, but I do not see how that is the case here.
But indeed the object is tried to access its stored value using a different type.
union u2 {
    int x;
    long y;
    char ca[2];
  };
Members x and y have different types (even if they might have the same representation).
But when it comes to unions one cannot say we are accessing one object through the type of the other (I know there is some debate about this, but there is a note in the standard that allows type punning through unions; I know notes are not normative, but I believe the intention was to make it valid).
It appears you are referring to this note in the standard:
If the member used to read the contents of a union object is not the same as the member last used to
store a value in the object, the appropriate part of the object representation of the value is reinterpreted
as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type
punning’’). This might be a trap representation.
You'd need to define what you mean by valid, but according to the above, it cannot mean "guaranteed behavior as defined by the standard", since it could lead to a "trap representation", i. e. undefined behavior if read.

Why can't a lvalue be resolved to the corresponding object's address, when the object is a bit-value or declared with the register storage class?

From C in a Nutshell:
An lvalue is an expression that designates an object, and it
can appear on the left side of an assignment operator.
An lvalue can always be resolved to the corresponding object’s
address, unless the object is a bit-field or a variable declared with the register storage class.
According to the second sentence from the quote, when the object is
a bit-value or a variable declared with the register storage class,
a lvalue can't be resolved to the corresponding object's address.
Why is that?
Given a lvalue which can't be resolved to the corresponding object's
address, how can the lvalue designate an object, and appear on the
left side of an assignment operator?
I think that the following three statements are equivalent:
a lvalue can't be resolved to the corresponding object's address,
a lvalue designate an object,
a lvalue can appear on the left side of an assignment operator.
and either of them can be used as a definition of lvalue. Am I
right?
Thanks.
The minimum addressability resolution is the char. If you want a bit field, that's one or more bits within a char so cannot have its own address, unless you were to allow addresses like 42.6 which would blow the heads off most coders :-)
Variables with register storage class generally can't be addressed because they're not necessarily stored anywhere in memory - that is, after all, what the register storage class means: try to keep this value in a register.
But, even though you cannot get an address for those objects, that doesn't mean you cannot assign to them. For objects held in registers, you just change the register.
And, for bit fields, you can just use the Boolean operations like and/or to manipulate parts of an addressable value.

What does 'designate an object' mean in C?

For example,
int x = 10;
we say that "x designates an int object which stores 10". But what does "designate" exactly mean? Does it mean x behaves like a label which refers to the whole chunk of memory?
x is an identifier.
There is an int object (i.e. a region of storage) containing the value 10.
The identifier x is associated with that int object.
The C standard uses the English word designate to express the relationship between an identifier and the object it identifies. You could say the same thing in several different ways. I said "associate" just now, there are many words we could choose. "x is a label for this region of memory" would be another way.
Note: designating is not limited to identifiers. Other expressions can designate an object too. For example *(&x) also designates the same object, as does *(&x + 0).
When an expression designates an object, the expression may be used to either assign a value to the object, or retrieve the value from the object. (The same syntax covers both of those cases; it depends on context whether the value is read or written).
The word lvalue means an expression that might designate an object (according to the above definition of 'designate').

How is an array of object[]s stored in memory?

As I understand it, the elements of an array are stored contiguously in memory, and accessing a particular one it is done by adding the product of the desired index and the size of each element with the base array address to find the address of the element.
Since in a language like C# I can create an array of object[]s and put whatever data type I want in it, how is each element of the array stored (and kept) at a uniform length if I used differently sized types while still allowing for random access?
This depends on the language in question, and what you mean by "object" -
As you mentioned C#, in C# (.NET), an object[] contains an array of references to individual object instances. The array is an array of references - the object instance still needs to be assigned to an element of the array. The references are of a uniform size, but the object instances themselves are stored separately, and do not have to be the same size.
This is the same in most languages when storing an array of "references" or "pointers", and not the object instances themselves.
Objects are reference types. The value at the address is actually a pointer to the true element.

C99: Is it possible to portably determine if two pointers point within the same aggregate?

In c99, my understanding is that comparing two pointers which do not point within the same aggregate results in undefined behavior. Given an aggregate A, a pointer p_good which is known to point within A, and a pointer p_unknown which may or may not point within A, is it possible to construct a portable test with defined behavior which determines whether it is safe to compare p_good and p_unknown?
Obviously, this test cannot itself fall afoul of the restrictions on comparing pointers.
I suspect that the answer is 'no', but I'd be happy to be shown otherwise.
You commented:
Another way to frame the question would be like this: Given the definition of an aggregate 'A' and a pointer p, is it possible to answer the question 'does p point within A' without violating the rule on inequality testing of pointers to different aggregates
The only way I can interpret this meaningfully is that you either have an object of type Aggregate type or a pointer to one. Then the answer is simple:
Pseudo-code:
bool p_in_A = false;
for (each element in Aggregate A)
if (&element == p)
p_in_A = true;
There is no way to tell whether a stray pointer belongs to an unknown aggregate object (or points to "between" elements in an aggregate).

Resources