GoogelAddUnit1

Wednesday, 9 March 2011

Structures & Unions1.

Structures, Unions, and Enumerations

Q.1
What’s the difference between these two declarations?
struct x1 { ... };
typedef struct { ... } x2;

Ans:
The first form declares a ‘structure tag’; the second declares a ‘typedef’. The main
difference is that you subsequently refer to the first type as struct x1 and the second
simply as x2.That is, the second declaration is of a slightly more abstract type-its
users don’t necessarily know that it is a structure, and the keyword struct is not used
when declaring instances of it.

Q.2
Why doesn’t the following code work?
struct x { ... };
x thestruct;

Ans:
C is not C++. Typedef names are not automatically generated for structure tags.

Q.3
Can a structure contain a pointer to itself?
Ans:
Most certainly.

Q4
What’s the best way of implementing opaque (abstract) data types in C?

Ans:
One good way is for clients to use structure pointers (perhaps additionally hidden
behind typedefs) which point to structure types which are not publicly defined.

Q.5
I came across some code that declared a structure like this:
struct name {
int namelen;
char namestr[1];
};
and then did some tricky allocation to make the namestr array act like it had several
elements. Is this legal or portable?

Ans:
This technique is popular, although Dennis Ritchie has called it ‘unwarranted
chumminess with the C implementation’. An official interpretation has deemed that
it is not strictly conforming to the C Standard, although it does seem to work under
all known implementations. (Compilers which check array bounds carefully might
issue warnings.) Another possibility is to declare the variable-size element very
large, rather than very small; in the case of the above example:
...
char namestr[MAXSIZE];
where MAXSIZE is larger than any name which will be stored. However, it looks
like this technique is disallowed by a strict interpretation of the Standard as well.
Furthermore, either of these ‘chummy’ structures must be used with care, since the
programmer knows more about their size than the compiler does. (In particular,
they can generally only be manipulated via pointers.)C9X will introduce the con-
cept of a ‘flexible array member’, which will allow the size of an array to be omitted
if it is the last member in a structure, thus providing a well-defined solution.

Q.6
Is there a way to compare structures automatically?

Ans:
No. There is no single, good way for a compiler to implement implicit structure
comparison (i.e., to support the == operator for structures) which is consistent with
C’s low-level flavor. A simple byte-by-byte comparison could founder on random
bits present in unused ‘holes’ in the structure (such padding is used to keep the
alignment of later fields correct; A field-by-field comparison might require unac-
ceptable amounts of repetitive code for large structures. If you need to compare two
structures, you’ll have to write your own function to do so, field by field.

Q.7
How can I pass constant values to functions which accept structure arguments?

Ans:
As of this writing, C has no way of generating anonymous structure values. You will
have to use a temporary structure variable or a little structure-building function. The
C9X Standard will introduce ‘compound literals’; one form of compound literal
will allow structure constants. For example, to pass a constant coordinate pair to a
plotpoint() function which expects a struct point, you will be able to call
plotpoint((struct point){1, 2});Combined with ‘designated initializers’ (another
C9X feature), it will also be possible to specify member values by
name:plotpoint((struct point){.x=1, .y=2});

Q.8
How can I read/write structures from/to data files?

Ans:
It is relatively straightforward to write a structure usingfwrite():fwrite(&somestruct,
sizeof somestruct, 1, fp);
and a corresponding fread() invocation can read it back in. However, data files so
written will *not* be portable. Note also that if the structure contains any pointers,
only the pointer values will be written, and they are most unlikely to be valid when
read back in. Finally, note that for widespread portability you must use the “b” flag
when fopening() the files;
A more portable solution, though it’s a bit more work initially, is to write a pair of
functions for writing and reading a structure, field-by-field, in a portable (perhaps
even human- readable) way.

Q.9
My compiler is leaving holes in structures, which is wasting space and preventing
‘binary’ I/O to external data files. Can I turn off the padding, or otherwise control
the alignment of structure fields?

Ans:
Your compiler may provide an extension to give you this control (perhaps a
#pragma; but there is no standard method.

Q.10
Why does sizeof() report a larger size than I expect for a structure type, as if there
were padding at the end?

Ans:
Structures may have this padding (as well as internal padding), if necessary, to en-
sure that alignment properties will be preserved when an array of contiguous struc-
tures is allocated. Even when the structure is not part of an array, the end padding
remains, so that sizeof() can always return a consistent size.

Q.11
How can I determine the byte offset of a field within a structure?

Ans:
ANSI C defines the offsetof() macro, which should be used if available; see <
stddef.h>. If you don’t have it, one possible implementation is #define offsetof(type,
mem) ((size_t) \ ((char *)&((type *)0)  > mem - (char *)(type *)0))This implemen-
tation is not 100% portable; some compilers may legitimately refuse to accept it.
 
Q.12
How can I access structure fields by name at run time?

Ans:
Build a table of names and offsets, using the offsetof() macro. The offset of field b
in struct a is
offsetb = offsetof(struct a, b)
If structp is a pointer to an instance of this structure, and field b is an int (with offset
as computed above), b’s value can be set indirectly with
*(int *)((char *)structp + offsetb) = value;

Q.13
This program works correctly, but it dumps core after it finishes. Why?
struct list {
char *item;
struct list *next;
}
/* Here is the main program. */
main(argc, argv)
{ ... }

Ans:
A missing semicolon causes main() to be declared as returning a structure. (The
connection is hard to see because of the intervening comment.) Since structure-
valued functions are usually implemented by adding a hidden return pointer, the
generated code for main() tries to accept three arguments, although only two are
passed (in this case, by the C start-up code).

Q.14
Can I initialize unions?

Ans:
The current C Standard allows an initializer for the first-named member of a union.
C9X will introduce ‘designated initializers’ which can be used to initialize
any member.

Q.15
What is the difference between an enumeration and a set of preprocessor #defines?

Ans:
At the present time, there is little difference. The C Standard says that enumerations
may be freely intermixed with other integral types, without errors. (If, on the other
hand, such intermixing were disallowed without explicit casts, judicious use of enu-
merations could catch certain programming errors.)Some advantages of enumera-
tions are that the numeric values are automatically assigned, that a debugger may be
able to display the symbolic values when enumeration variables are examined, and
that they obey block scope. (A compiler may also generate non-fatal warnings when
enumerations and integers are indiscriminately mixed, since doing so can still be
considered bad style even though it is not strictly illegal.) A disadvantage is that the
programmer has little control over those non-fatal warnings; some programmers
also resent not having control over the sizes of enumeration variables.

Q.16
Is there an easy way to print enumeration values symbolically?

Ans:
No. You can write a little function to map an enumeration constant to a string. (For
debugging purposes, a good debugger should automatically print enumeration con-
stants symbolically.

Q.14.
What is the output of this program?
struct num
{
int no;
char name[25];
};
void main()
{
struct num n1[]={{25,“rose”},{20,”gulmohar”},{8,“geranium”},{11,“dahalia”}};
printf(“%d%d” ,n1[2].no,(*&n1+2)->no+1);
}

Ans:
8 9

Q15
. What is the output of this program?
struct Foo
{
char *pName;
};
main()
{
struct Foo *obj = malloc(sizeof(struct Foo));
clrscr();
strcpy(obj->pName,“Your Name”);
printf(“%s”, obj->pName);}.

Ans:
Your Name

Q16.
What is the output of this program?
struct Foo
{
char *pName;
char *pAddress;
};
main()
{
 struct Foo *obj = malloc(sizeof(struct Foo));
clrscr();
obj->pName = malloc(100);
obj->pAddress = malloc(100);
strcpy(obj->pName,“Your Name”);
strcpy(obj->pAddress, “Your Address”);
free(obj);
printf(“%s”, obj->pName);
printf(“%s”, obj->pAddress);
}

Ans:
printd Nothing, as after free(obj), no memory is there containing
obj->pName   &   pbj->pAddress

Q.17
What is the output of this program?
main()
{
char *a = “Hello ”;
char *b = “World”;
clrscr();
printf(“%s”, strcat(a,b));
}

Ans:
Hello World

Q.18
What is the output of this program?
main()
{
char *a = “Hello”;
char *b = “World”;
clrscr();
printf(“%s”, strcpy(a,b));
}

Ans:
World, copies World on a, overwrites Hello in a.

Q.19
What is the output of this program?
union u
{
struct st
{
int i : 4;
int j : 4;
int k : 4;
int l;
}st;
int i;
}u;
main()
{
u.i = 100;
printf(“%d, %d, %d”,u.i, u.st.i, u.st.l);
}

Ans:
100, 4, 0

Q.20
What is the output of this program?
union u
{
union u
{
int i;
int j;
}a[10];
int b[10];
}u;
main()
{
printf(“n%d”, sizeof(u));
printf(“  %d”, sizeof(u.a));
//      printf(“%d”, sizeof(u.a[4].i));
}

Ans:
20, 200, error for 3rd printf()

No comments:

Post a Comment