Unions and values stored - c

I know that a union allows to store different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time. Consider this program:
#include <stdio.h>
union integer {
short s;
int i;
long l;
};
int main() {
union integer I;
scanf("%hi", &I.s);
scanf("%d", &I.i);
scanf("%ld", &I.l);
printf("%hi - %d - %ld ", I.s, I.i, I.l );
}
Suppose we enter the values 11, 55, 13 the program will give as output
13 - 13 - 13, no problem here. However, if i were to create three different variables of type struct integer
#include <stdio.h>
union integer {
short s;
int i;
long l;
};
int main() {
union integer S;
union integer I;
union integer L;
scanf("%hi", &S.s);
scanf("%d", &I.i);
scanf("%ld", &L.l);
printf("%hi - %d - %ld ", S.s, I.i, L.l );
}
than all the values will be preserved.
How come? By using three variables am i actually using three unions, each holding just one value?

The union members s, i and l of the same variable share the same memory. Reading a different member than you have written last is undefined behavior.
If you define 3 variables of the same union type it is not much different from defining 3 variables of type int. Every variable has its own memory, and every variable can hold only one of the union members.

What output do you expect from this code? Three different values or the same one?
#include <stdio.h>
int main() {
short S;
int I;
long L;
scanf("%hi", &S);
scanf("%d", &I);
scanf("%ld", &L);
printf("%hi - %d - %ld ", S, I, L );
}
You are declaring three separate variables, even if they are unions, all of them have their storage.

Related

Variable-sized object may not be initialized

In line 6 it appears that int variable-sized object may not be initialized, what is the problem with the int? How can i fix it?
#include <stdio.h>
int main (void)
{
const int SIZE=5;
//variable remain constant
int grades[SIZE]= {66,50,93,67,100};
double sum= 0.0;
int i;
printf("\nMy grades are:\n");
for (i=0;i<SIZE;i++)//0 first character and < because last character is sentinel
printf("%d\t",grades[i]);
printf("\n\n");
for (i=0;i<SIZE;i++) //analyze data in list and retrieve it
sum=sum+grades[i];
printf("My average is %.2f\n\n",sum/SIZE); //sum /size for average with decimals
return 0;
}
I expected to find an average using simple one-dimensional array, but that problem doesn't let me run the program
SIZE is not a constant.
SIZE is a const int, but, as strange as it sounds, it is still not a constant. grades[SIZE] is a variable length array. Variable length arrays may not be initialized. *1
const int SIZE=5;
int grades[SIZE]= {66,50,93,67,100};// error: variable-sized object may not be initialized
Alternate 1: Use a constant
5 is a constant of type int.
#define SIZE 5
int grades[SIZE]= {66,50,93,67,100};
Alternate 2: Promptly assign
Assign or copy in the values from some source, perhaps from a compound literal.
const int SIZE=5;
int grades[SIZE];
v-----------------------v compound literal
memcpy(grades, (int []){66,50,93,67,100}, sizeof grades);
*1
Perhaps a future version of C will allow this.

The behaviour of unions in C

I am really dumb. Please help me out by explaining the output:
#include <stdio.h>
union x
{
int a;
char b;
double c;
};
int main()
{
union x x[3] = {{1}, {'a'}, {1.2}};
int i;
for(i = 0; i < 3; i++)
printf("%d , %d , %lf\n", x[i].a, x[i].b, x[i].c);
return 0;
}
Output:
When you provide an initial value for a union, the compiler assigns it to the first member of the union. So, given:
union x
{
int a;
char b;
double c;
};
and:
union x x[3] = {{1}, {'a'}, {1.2}};
the compiler initializes x[0].a to 1, x[1].a to a, and x[2].a to 1.2. The compiler does not use the types of the initial values to match them to union elements. It merely initializes the first member with the value you give it. If there is a difference in types, the compiler converts the value to the type of the first member. (If that is a legal conversion. Otherwise, the compiler should provide a warning or error message.)
To initialize specific members of the union, you can use designated initializers, in which you explicitly name the member of the union you want to initialize:
union x x[3] = { { .a = 1 }, { .b = 'a' }, { .c = 1.2 } };
think of a union as an allocated space in the memory (size of which is the largest element in the union) each union defined can be interpeted as either element of the union so you can look at that allocated memory as a different type
https://www.tutorialspoint.com/cprogramming/c_unions.htm
taken from the link:
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
int main( ) {
union Data data;
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
return 0;
}
as you can see it has defined one union but it used three different times as a different type
EDIT:
by C99 when initalizing a union the first element is the one initialized hence the value 1.2 is casted to 1 where in the case of the char the casting works as expected
if you reorder the elements in your union you will get:
0 , 0 , 1.000000
0 , 0 , 97.000000
858993459 , 51 , 1.200000
for further explanation:
http://en.cppreference.com/w/c/language/struct_initialization
When initializing a struct, the first initializer in the list
initializes the first declared member (unless a designator is
specified) (since C99), and all subsequent initializers without
designators (since C99)initialize the struct members declared after
the one initialized by the previous expression.
as mentioned in other comments there is a lot of information on the issue and you should research it further, but i hope this gives you a starting point
As per C99 standard, you can still initialize your union with one-liner using designated initializers without losing your data:
union x x[3] = {{.a = 1}, {.b = 'a'}, {.c = 1.2}};
This will force compiler to use particular union's member, rather than type of first declared one (which is int in your case).
Output:
1, 1, 0.000000
97, 97, 0.000000
858993459, 51, 1.200000
Proof.

Bit fields giving segmentation fault

This is C language. When I run my following program, no matter how small values I give, I get runtime segmentation fault error. Please help me find out the cause of this.
#include <stdio.h>
#include <stdlib.h>
struct date
{
unsigned day:
5;
unsigned month:
4;
unsigned year:
12;
};
struct emp
{
char name[10];
struct date d;
};
int compare(const void * a, const void * b)
{
struct emp *orderA = (struct emp *)a;
struct emp *orderB = (struct emp *)b;
return ( orderA->d.year - orderB->d.year );
}
int main ()
{
int i;
struct emp e[5];
for (i = 0;i < 5;i++)
{
scanf("%s %d %d %d", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
qsort(e, 5, sizeof(struct emp), compare);
for (i = 0;i < 5;i++)
{
printf("%s %d %d %d\n", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
return 0;
}
When you want scanf() to scan your stuff, you have to pass addresses of stuff, not the actual stuff. (If you do not pass the address of something to scanf(), then how can scanf() store a value in it?)
Now, in C when you refer to an array such as e[i].name you are actually referring to the address of the first element of the array, so you do not have to do anything special about that. (Besides to be careful to not enter more than 9 characters for name, wh00ps, that's extremely unsafe, be careful!)
But with integers, such as e[i].d.day etc, you can't just pass the int as it is, because scanf() expects pointers, so it will treat your int as a pointer to an int, so it will allow the user to enter a number, and then it will try to store the number at the location pointed by that pointer, which is just some random location in memory, and thus the segfault.
So, when you want to scan an int, you have to pass the address of the int, like this: &e[i].d.day
Except that when the integer is a field of a record, you cannot take its address, because it does not have an address of its own, it lives within some bits stored at an address.
So, I am afraid you are going to have to write a special function for reading those struct dates of yours, which will have to declare individual ints, pass their addresses to scanf(), and then store the resulting values in a struct date.

Whats wrong with this simple c program?

I want to know why this program, that i create just for practice, don't works properly. The program asks for 5 numbers that put in an array called "array". There are also 2 VOID functions, one for get the numbers, that uses a for cicle and scanf instruction , and another, that has to print the 5 numbers in the array. The problem is that the numbers printed are only the firsts 4. What's wrong?
P.S. Sorry for my ignorance but i'm a beginner. Here's the code
#include <stdio.h>
#include <stdlib.h>
void
array_print(int array[],size_t size){
int i;
for(i=0;i<size;i++){
printf("%i ",array[i]);
}
}
void
get_num(int array[],size_t size){
int i;
for(i=0;i<size;i++){
scanf("%i",&array[i]);
}
}
int
main(){
int array[5];
size_t size;
size=sizeof(int);
printf("Insert 5 numbers: ");
get_num(array,size);
array_print(array,size);
return 0;
}
In the environment where you run the program sizeof(int) is equal to 4.
The size of the array can be calculated like
size = sizeof( array ) / sizeof( int );
Take into account the type of the value returned by the operator sizeof is size_t. So it would be better to use this type for the size of the array.
Also you could introduce a manifest constant for number 5. As for example
#define N 5
and declare the array like
int array[N];
Or if the compiler supports variable length arrays you could write
int main( void )
^^^^^^^^^^^^^^^^
{
const size_t N = 5;
int array[N];
//...
The architecture of the compiler in which you're executing your code is 32bit so the size of int is 32bits = 4 bytes.
size = sizeof(int)
will return
size = 4
and you will be only able to enter four values.

How to find the size of a variable without using sizeof

Let us assume I have declared the variable 'i' of certain datatype (might be int, char, float or double) ...
NOTE: Simply consider that 'i' is declared and dont bother if it is an int or char or float or double datatype. Since I want a generic solution I am simply mentioning that variable 'i' can be of any one of the datatypes namely int, char, float or double.
Now can I find the size of the variable 'i' without sizeof operator?
You can use the following macro, taken from here:
#define sizeof_var( var ) ((size_t)(&(var)+1)-(size_t)(&(var)))
The idea is to use pointer arithmetic ((&(var)+1)) to determine the offset of the variable, and then subtract the original address of the variable, yielding its size. For example, if you have an int16_t i variable located at 0x0002, you would be subtracting 0x0002 from 0x0006, thereby obtaining 0x4 or 4 bytes.
However, I don't really see a valid reason not to use sizeof, but I'm sure you must have one.
It's been ages since I wrote any C code and I was never good at it, but this looks about right:
int i = 1;
size_t size = (char*)(&i+1)-(char*)(&i);
printf("%zi\n", size);
I'm sure someone can tell me plenty of reasons why this is wrong, but it prints a reasonable value for me.
This works..
int main() {
int a; //try changing this to char/double/float etc each time//
char *p1, *p2;
p1 = &a;
p2 = (&a) + 1;
printf("size of variable is:%d\n", p2 - p1);
}
int *a, *b,c,d;/* one must remove the declaration of c from here*/
int c=10;
a=&c;
b=a;
a++;
d=(int)a-(int)b;
printf("size is %d",d);
I hope that below code would solve your problem in c++ without using sizeof() operator
for any variables like (int, char, float, double, char, short and many more...)
here I take integer,
int a;
then
show it as byte addressable output,
cout<<(char *)(&a + 1) - (char *)(&a);
This should work.
#define xsizeof(x) (char *)(&x+1) - (char *)&x
Try this,
#define sizeof_type( type ) ((size_t)((type*)1000 + 1 )-(size_t)((type*)1000))
For the following user-defined datatype,
struct x
{
char c;
int i;
};
sizeof_type(x) = 8
(size_t)((x*)1000 + 1 ) = 1008
(size_t)((x*)1000) = 1000
This should give you the size of your variable
#define mySizeof(type) ((uint)((type *)0+1))
Program to find Size of the variable without using sizeof operator
#include<stdio.h>
int main()
{
int *p,*q;
int no;
p=&no;
printf("Address at p=%u\n",p);
q=((&no)+1);
printf("Address at q=%u\n",q);
printf("Size of int 'no': %d Bytes\n",(int)q-(int)p);
char *cp,*cq;
char ch;
cp=&ch;
printf("\nAddress at cp=%u\n",cp);
cq=cp+1;
printf("Address at cq=%u\n",cq);
printf("Size of Char=%u Byte\n",(int)cq-(int)cp);
float *fp,*fq;
float f;
fp=&f;
printf("\nAddress at fp=%u\n",fp);
fq=fp+1;
printf("Address at fq=%u\n",fq);
printf("Size of Float=%u Bytes\n",(int)fq-(int)fp);
return 0;
}
#define GET_SIZE(myvar) ((char)( ((char*)(&myvar+1) )- ((char*)&myvar) ))
#include<stdio.h>
#include<conio.h>
struct size1
{
int a;
char b;
float c;
};
void main()
{
struct size1 *sptr=0; //declared one pointer to struct and initialise it to zero//
sptr++;
printf("size:%d\n",*sptr);
getch();
}
Below statement will give generic solution:
printf("%li\n", (void *)(&i + 1) - (void *)(&i));
i is a variable name, which can be any data type (char, short, int, float, double, struct).

Resources