In K&R C(2nd) 127p,
The main change made by the ANSI standard is to define structure assignment-structures may be copied and assigned to, passed to functions, and returned by functions. This has been supported by most compilers for many years, but the properties are now precisely defined. Automatic structures and arrays may now also be initialized.
What's the meaning of 'Automatic structures and arrays may now also be initialized.'? I read this.
And It's written at 261p(the part of appendix C. summary of changes)
Automatic structures, unions, and arrays may be initialized, albeit in a restricted way.
I got following code is not allowed in K&R C(1st).
int main()
{
int a[3] = { 1, 2, 3 };
struct { int a; char b; } x = { 1, 2 };
}
Could you explain then how were arrays and structures initialized in that time?It's a bit confusing where to focus, 'automatic' to 'global' or 'now be initialized' to 'couldn't be initialized'.
As far as I understand, that point of time initialization at the time of definition were not allowed for structure, union and array type variables which automatic storage. They would have to be assigned values, using separate assignment statements. Example:
For array, it'll be looping over elements and assigning one by one.
For structures, accessing members and assigning them.
Related
Just curious, what actually happens if I define a zero-length array int array[0]; in code? GCC doesn't complain at all.
Sample Program
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Clarification
I'm actually trying to figure out if zero-length arrays initialised this way, instead of being pointed at like the variable length in Darhazer's comments, are optimised out or not.
This is because I have to release some code out into the wild, so I'm trying to figure out if I have to handle cases where the SIZE is defined as 0, which happens in some code with a statically defined int array[SIZE];
I was actually surprised that GCC does not complain, which led to my question. From the answers I've received, I believe the lack of a warning is largely due to supporting old code which has not been updated with the new [] syntax.
Because I was mainly wondering about the error, I am tagging Lundin's answer as correct (Nawaz's was first, but it wasn't as complete) -- the others were pointing out its actual use for tail-padded structures, while relevant, isn't exactly what I was looking for.
An array cannot have zero size.
ISO 9899:2011 6.7.6.2:
If the expression is a constant expression, it shall have a value greater than zero.
The above text is true both for a plain array (paragraph 1). For a VLA (variable length array), the behavior is undefined if the expression's value is less than or equal to zero (paragraph 5). This is normative text in the C standard. A compiler is not allowed to implement it differently.
gcc -std=c99 -pedantic gives a warning for the non-VLA case.
As per the standard, it is not allowed.
However it's been current practice in C compilers to treat those declarations as a flexible array member (FAM) declaration:
C99 6.7.2.1, §16: As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.
The standard syntax of a FAM is:
struct Array {
size_t size;
int content[];
};
The idea is that you would then allocate it so:
void foo(size_t x) {
Array* array = malloc(sizeof(size_t) + x * sizeof(int));
array->size = x;
for (size_t i = 0; i != x; ++i) {
array->content[i] = 0;
}
}
You might also use it statically (gcc extension):
Array a = { 3, { 1, 2, 3 } };
This is also known as tail-padded structures (this term predates the publication of the C99 Standard) or struct hack (thanks to Joe Wreschnig for pointing it out).
However this syntax was standardized (and the effects guaranteed) only lately in C99. Before a constant size was necessary.
1 was the portable way to go, though it was rather strange.
0 was better at indicating intent, but not legal as far as the Standard was concerned and supported as an extension by some compilers (including gcc).
The tail padding practice, however, relies on the fact that storage is available (careful malloc) so is not suited to stack usage in general.
In Standard C and C++, zero-size array is not allowed..
If you're using GCC, compile it with -pedantic option. It will give warning, saying:
zero.c:3:6: warning: ISO C forbids zero-size array 'a' [-pedantic]
In case of C++, it gives similar warning.
It's totally illegal, and always has been, but a lot of compilers
neglect to signal the error. I'm not sure why you want to do this.
The one use I know of is to trigger a compile time error from a boolean:
char someCondition[ condition ];
If condition is a false, then I get a compile time error. Because
compilers do allow this, however, I've taken to using:
char someCondition[ 2 * condition - 1 ];
This gives a size of either 1 or -1, and I've never found a compiler
which would accept a size of -1.
Another use of zero-length arrays is for making variable-length object (pre-C99). Zero-length arrays are different from flexible arrays which have [] without 0.
Quoted from gcc doc:
Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure that is really a header for a variable-length object:
struct line {
int length;
char contents[0];
};
struct line *thisline = (struct line *)
malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
In ISO C99, you would use a flexible array member, which is slightly different in syntax and semantics:
Flexible array members are written as contents[] without the 0.
Flexible array members have incomplete type, and so the sizeof operator may not be applied.
A real-world example is zero-length arrays of struct kdbus_item in kdbus.h (a Linux kernel module).
I'll add that there is a whole page of the online documentation of gcc on this argument.
Some quotes:
Zero-length arrays are allowed in GNU C.
In ISO C90, you would have to give contents a length of 1
and
GCC versions before 3.0 allowed zero-length arrays to be statically initialized, as if they were flexible arrays. In addition to those cases that were useful, it also allowed initializations in situations that would corrupt later data
so you could
int arr[0] = { 1 };
and boom :-)
Zero-size array declarations within structs would be useful if they were allowed, and if the semantics were such that (1) they would force alignment but otherwise not allocate any space, and (2) indexing the array would be considered defined behavior in the case where the resulting pointer would be within the same block of memory as the struct. Such behavior was never permitted by any C standard, but some older compilers allowed it before it became standard for compilers to allow incomplete array declarations with empty brackets.
The struct hack, as commonly implemented using an array of size 1, is dodgy and I don't think there's any requirement that compilers refrain from breaking it. For example, I would expect that if a compiler sees int a[1], it would be within its rights to regard a[i] as a[0]. If someone tries to work around the alignment issues of the struct hack via something like
typedef struct {
uint32_t size;
uint8_t data[4]; // Use four, to avoid having padding throw off the size of the struct
}
a compiler might get clever and assume the array size really is four:
; As written
foo = myStruct->data[i];
; As interpreted (assuming little-endian hardware)
foo = ((*(uint32_t*)myStruct->data) >> (i << 3)) & 0xFF;
Such an optimization might be reasonable, especially if myStruct->data could be loaded into a register in the same operation as myStruct->size. I know nothing in the standard that would forbid such optimization, though of course it would break any code which might expect to access stuff beyond the fourth element.
Definitely you can't have zero sized arrays by standard, but actually every most popular compiler gives you to do that. So I will try to explain why it can be bad
#include <cstdio>
int main() {
struct A {
A() {
printf("A()\n");
}
~A() {
printf("~A()\n");
}
int empty[0];
};
A vals[3];
}
I am like a human would expect such output:
A()
A()
A()
~A()
~A()
~A()
Clang prints this:
A()
~A()
GCC prints this:
A()
A()
A()
It is totally strange, so it is a good reason not to use empty arrays in C++ if you can.
Also there is extension in GNU C, which gives you to create zero length array in C, but as I understand it right, there should be at least one member in structure prior, or you will get very strange examples as above if you use C++.
#include<stdio.h>
struct str
{
static int a ;
int b ;
} s ;
int main()
{
static int p , k ;
printf("%d %d",sizeof(p),sizeof(s));
getchar();
return 0;
}
above code is giving errors . But if I redefine the first member of the structure to 'int' rather than 'static int' then it runs fine . Why static members are not allowed in the structure and what is its significance ?
There's simply no such feature in C language. And there's no meaningful conceptual framework for such feature in C.
You see, in C++ terms, there's only one relevant difference between a static member variable and an ordinary global variable: the scope in which its name is declared and the corresponding naming syntax. A global variable could be called a, while a static member of the class would be called SomeClass::a. Besides scoped naming, there are no other differences. (I deliberately ignore other C++-specific features, like access control, since they don't exist in C and this question is really about C.)
In C language a struct type does not introduce its own scope. There's no such naming syntax as SomeStruct::a in C language. For this reason there's simply no reason to have static members in structs. You can declare a global variable instead and achieve the same effect. Call your global variable str_a to convey the intent to "associate" it with struct str and just think of that variable as a pseudo-static member of struct str.
Formally speaking, one could do it the same way in C++, i.e. completely ignore this feature of C++ language and use global functions and variables instead of static function and variables inside classes. However, by doing that one would forsake all member access control features of C++. And these features are really worth having. C language has no access control features, meaning that in C one loses [almost] nothing.
The language just doesn't allow it. There's no deeper reason other than that it's not part of the design. You can always achieve the same behaviour with a separate global variable like this:
struct str
{
int b;
} s;
int str_a;
Note that it would be something entirely different to have a non-static int a; inside your struct, which would be a distinct subelement of every object of type struct str.
(Note also that in C++, a language evolved from C, static class members do exist and behave exactly like the workaround I described above, only that the name of the global variable is tightly associated to the name of the class.)
A static modifier is to declare your variable in the global scope in your file and a static modifier in a function creates a variable with a persistant value limited to the scope of this functions. And you can not share the value of this integer between your instances of your struct.
This is not and cannot be supported in C ;)
Why do you want to use a static member in a struct? maybe there is (there must be) a better soluation.
You have good answers here: http://cboard.cprogramming.com/c-programming/123691-static-variable-structure.html
generally speaking you don't have any gain from declaring it static, but if you still wish to it , you may migrate to c++ or declare the whole struct as static.
No, not in C. I believe C++ can do this and it means there is one copy of a that is shared amongst all instances of the struct str structure.
If you want to do something similar in C, you have a few options (there may be more, I just can't think of them at the moment).
The first is to break out the common variable with something like:
int struct_str_static_a;
struct str {
int b;
} s;
That way, there is only one copy of a shared by all instances of the structure - each instance still gets its own copy of b.
A slight modification to that is to introduce a pointer to that common variable and initialise the pointer:
int struct_str_static_a;
struct str {
int *pA;
int b;
} s;
:
s.pA = &struct_str_static_a;
Then you can use *(s.pA) where before you would have used s.a. Because every instance of struct str has its own pA pointer that points to a single a, that gives you a similar effect. However, it's a torturous road to follow.
The third option is to get yourself on the next ISO C working group and put this forward as a change to the language. However, that's going to require a fair bit of effort from yourself for the next ten years or so, probably not worth the effort :-)
Any historical or logical reasons behind it?
Explanation:
when you pass an array to a function in C you actually only pass a pointer to an array.
However, when you pass a struct, you can either pass a copy of the struct or the pointer.
//this:
int function(int array[10])
// is equivalent to this:
int function(int *array)
//and they both pass a pointer
//but this:
int function(struct tag name)
//passes a struct by value, where as this:
int function(struct tag *name)
//passes a pointer to it.
Why the difference?
In the original K&R, you could not pass structs by value. That was a syntax error. Because many compiler vendors offered it as an extension, pass-by-value eventually made its way into the standard.
Why the restriction, and why the evolution? The machines that C was developed on were tiny. Segment sizes of 64 kilobytes were common. Memory was precious, so why copy something when you could just pass the address? Duplicating a 64-byte structure on the stack was an error, probably not even what the user intended.
By the mid-1990s, that wasn't true anymore. 32-bit addressing and RAM of 4 MB or more were common. The restriction was a hinderance and led to some complexity, because without const a structure passed by reference could be modified, perhaps unwittingly.
Why not do the same with arrays? No demand. Arrays and pointers are closely related in C, as you know. The C standard library depends heavily on passing by reference, consider memset and strcpy. Whereas passing a struct by value meant just dropping the & on the call, passing an array by value would have entailed adding new syntax. A compiler vendor that offered, say, by value as C syntax would have been laughed out of the conference.
int function(int array[10]) and int function(int *array) are the same because of 6.7.5.3 Function declarators (including prototypes) (http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf page 118)
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if
any) are those specified within the [ and ] of the array type
derivation. If the keyword static also appears within the [ and
] of the array type derivation, then for each call to the
function, the value of the corresponding actual argument shall
provide access to the first element of an array with at least as many
elements as specified by the size expression
.
Of course, you can pass an array by value; all you need to do is wrap it in a struct. But that only works if the array has a definite (and non-variable) size. You can include an indefinitely sized array in a struct, but the resulting type is incomplete and can only be used as the target of a pointer.
That's probably as close as we're going to get to an explanation. The vast majority of arrays passed as arguments are not of fixed size, and passing them by value would not be possible, even if it were intended, which is also unlikely.
There is a similar (but different) decay with functions; a function cannot be passed as an argument, only function pointers. Since it would be tedious to explicitly write & every time you wanted to refer to a function, the language takes care of it for you.
On the whole, questions of the form "Why is this language like this snd not like that?" can only be answered "because that's how it is".
Types are different in both function declarations -
struct tag /* and */ struct tag *
One is structure variable whereas another is pointer to structure.
You can do similar with structures -
int function(struct tag name[]) /*--> int function(struct tag *name) */
These above would be equivalent.
structs are used for declaring own kind of data types with primitive data types like int,float,long(or structs of structs) etc. they are supposed to hold a few of them e.g. struct of students will contain id,name,rollno,subjects,etc. so mostly any struct element will contain 10-20 fields at most (in logical cases), so when you pass a struct to a function, it has to copy 40-100 bytes approx. to make copy of that struct variables. where as arrays can be of huge size and are used to store same kind of information. they can be of size 10^7 in case of integers so if we implement a language to copy whole array for function calls it may have to copy (10^7)*4 bytes which is a huge amount and will impact the performance badly.and typical size of arrays is 10^4 to 10^6 which is still a lot. but if you create struct of array of int(or any other array) you can pass it to a function as a copy of that array. e.g.
#include<stdio.h>
typedef struct {
int arr[10];
}arrayStruct;
void change(arrayStruct a){
a.arr[2]=5;
}
int main(){
arrayStruct a;
for(int i=0;i<10;i++){
a.arr[i]=i;
}
printf("Before:\n");
for(int i=0;i<10;i++){
printf("%d ",a.arr[i]);
}
change(a);
printf("\nAfter:\n");
for(int i=0;i<10;i++){
printf("%d ",a.arr[i]);
}
return 0;
}
this is not done in most of the cases but few times when you need to pass arrays but don't want to alter the contents of them but also require some kind of changes to their copies and want to return that copy you can use this kind of structs of arrays and return them from functions of return type of structs e.g.
arrayStruct returnChange(arrayStruct a){
a.arr[2]=332;
return a;
}
Arrays and structures in C store data in memory which is contiguous. Then why is that C does not allow direct copying of arrays using "=" where as it is allowed for structure.
Example:
int a[3] = {1,2,3};
int b[3];
b = a; // why is this not allowed.
struct book b1, b2;
b1.page = 100;
b1.price = 10.0;
b2 = b1; // Why is this allowed
For the first question
You cannot directly write to an array, you can write only to the individual cells to an array.
You can use a for loop to initialize array b or memcpy(&b, &a, sizeof b);
And with the structs the compiler does the memcpy for you.
Correct me if I am wrong.
When you type : b=a , the compiler expects that you are assigning an array to b, but a is just a pointer to the location where the first element of the array is stored so there is a type mismatch.This is why printf("%d",*a); will print 1.
And as for why structures can be assigned, it is because b1 and b2 in the above example are basically variables of the datatype book and variables can be assigned.When variables are assigned the contents are copied and they don't refer to the same memory location.This example might explain what i am saying more clearly:
#include<stdio.h>
typedef struct{int a;}num;
int main()
{
num b,c;
b.a = 10;
c=b;
b.a =11;
printf("%d\n",(c.a));
return 0;
}
The output is 10. This proves that b and c in this example do not point to the same memory.hope this helps.
Assignment requires that the type and therefore size of whatever is being assigned is known to the compiler. So an assignment of form
a = b;
requires that the types of a and b are both known to the compiler. If the types are the same (e.g. both a and b are of type int) then the compiler can simply copy b into a by whatever instructions it deems are most efficient. If the types are different, but an implicit promotion or type conversion is allowed, then the assignment is also possible after doing a promotion. For example, if a is of type long and b is of type short, then b will be implicitly promoted to long and the result of that promotion stored in a.
This doesn't work for arrays, because the size of an array (calculated as the size of its elements multiplied by number of elements) is not necessarily known. One compilation unit (aka source file) may have a declaration (possibly by including a header file)
extern int a[];
extern int b[];
void some_func()
{
a = b;
}
which tells the compiler that a and b are arrays of int, but that they will be defined (which includes giving them a size) by another compilation unit. Another compilation unit may then do;
extern int a[];
int a[] = {3,1,4,2,3}; /* definition of a */
and a third compilation unit may similarly define b as an array of 27 elements.
Once the object files are linked into a single executable, the usages of a and b in all compilation units are associated, and all operations on them refer to the same definitions.
The problem with this comes about because the separate compilation model is a core feature of C. So the compiler, when chewing on the first compilation unit above, has no information about the size of the arrays since it has no visibility of other compilation units, and is required to succeed or diagnose errors without referring to them. Since there is no information about the number of elements in either array available to the first compilation unit, there is no way to work out how many elements to copy from one array to another. The handling of this in C is that the assignment a = b is a diagnosable error in the function some_func().
There are alternative approaches (and some other programming languages handle such cases differently) but they are generally associated with other trade-offs.
The considerations doesn't generally affect struct types, since their size is known at compile time. So, if a and b are of the same struct type, the assignment a = b is possible - and can be implemented by (say) a call of memcpy().
Note: I am making some deliberate over-simplification in the explanation above, such as not considering the case of structs with flexible array members (from C99). Discussing such cases would make the discussion above more complicated, without changing the core considerations.
int array[5][3];
(obviously) creates a multi-dimensional C array of 5 by 3. However,
int x = 5;
int array[x][3];
does not. I've always thought it would. What don't I understand about C arrays? If they only allow a constant to define the length of a C array, is there a way to get around this in some way?
In ANSI C (aka C89), all array dimensions must be compile-time integer constants (this excludes variables declared as const). The one exception is that the first array dimension can be written as an empty set of brackets in certain contexts, such as function parameters, extern declarations, and initializations. For example:
// The first parameter is a pointer to an array of char with 5 columns and an
// unknown number of rows. It's equivalent to 'char (*array_param)[5]', i.e.
// "pointer to array 5 of char" (this only applies to function parameters).
void some_function(char array_param[][5])
{
array_param[2][3] = 'c'; // Accesses the (2*5 + 3)rd element
}
// Declare a global 2D array with 5 columns and an unknown number of rows
extern char global_array[][5];
// Declare a 3x2 array. The first dimension is determined by the number of
// initializer elements
int my_array[][2] = {{1, 2}, {3, 4}, {5, 6}};
C99 added a new feature called variable-length arrays (VLAs), where the first dimension is allowed to be a non-constant, but only for arrays declared on the stack (i.e. those with automatic storage). Global arrays (i.e. those with static storage) cannot be VLAs. For example:
void some_function(int x)
{
// Declare VLA on the stack with x rows and 5 columns. If the allocation
// fails because there's not enough stack space, the behavior is undefined.
// You'll probably crash with a segmentation fault/access violation, but
// when and where could be unpredictable.
int my_vla[x][5];
}
Note that the latest edition of the C standard, C11, makes VLAs optional. Objective-C is based off of C99 and supports VLAs. C++ does not have VLAs, although many C/C++ compilers such as g++ which support VLAs in their C implementation also support VLAs in C++ as an extension.
int x = 5;
int array[x][3];
Yes, it does. It's a C99 variable length array. Be sure to switch to C99 mode and be sure to have array declared at block or function scope. Variable length arrays cannot be declared at file scope.
Try:
const int x=5;
int array[x][3];
As you said x has to be a constant or else think what would happen if in the middle of the program you changed the value of x,what would be the dimension of array:(
But by declaring it constan if you change the value of x you get a compile error.