-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.c
More file actions
163 lines (135 loc) · 3.27 KB
/
code.c
File metadata and controls
163 lines (135 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <stdio.h>
int sum(int, int);
int greaterthan10(int x);
int shift_left2_rightn(int, int);
unsigned float2bit(float);
double bit2double(unsigned, unsigned);
float bit2float(unsigned dword);
unsigned long long double2bit(double);
int main()
{
char c = -1;
unsigned a = (unsigned) c; // Sign extension! Only depends on source signedness
printf("%u\n", a);
unsigned char uc = 255;
int b = (int) uc; // Zero extension!
printf("%u\n", b);
// conclude that the choice of zero or sign extension depends on the
// type of the source, not the destination.
printf("%d\n", 0xFF); // C compiler treats the literal 0xFF as an int with value 0x000000FF
// it just pads it with zeros until the number is 32-bit
// Bit representations of floating point type
float f = 0.11;
printf("%f ... %u\n", f, float2bit(f)); // the float2bit function shows you the bit pattern of f
// never try to printf a floating point number using any format specifier besides %f, %e, or %g
union {
struct {
short a;
int b;
short c;
} internal1;
struct {
double d;
} internal2;
} u1;
union {
struct {
short a;
short b;
int c;
} internal1;
struct {
double d;
} internal2;
} u2;
printf("sizeof(u1) = %d\n", sizeof(u1));
printf("sizeof(u2) = %d\n", sizeof(u2));
// u2 and u1 are functionally equivalent, but u1 takes up twice the memory
// due to the misalignment of the members of its internal1 struct.
// In contrast, u2 declares its members in such a way that no padding is necessary
// to align a, b, c, and d simultaneously.
struct {
int a;
int b;
char c;
} s1[2];
printf("\nsizeof(s1) = %d\n", sizeof(s1));
// padding is put at the end of each element of s1 so that subsequent elements are aligned
int fun(int x, int *p);
int (*fp)(int, int *);
fp = fun;
int y = 1;
int result = fp(3, &y); // no need to use *... fp is known to be a function pointer and x86 jumps to its address
unsigned ui = 0x4427aaaf;
printf("%f\n", bit2float(ui));
unsigned long long ull = double2bit(60000.45);
printf("ull = %d\n", ull);
return 0;
}
int fun(int x, int *p)
{
return 0;
}
unsigned float2bit(float f)
{
union {
float f;
unsigned u;
} temp;
temp.f = f;
return temp.u; // return the bit representation of f (same 4 bytes of memory, but interpreted as unsigned)
}
unsigned long long double2bit(double d)
{
union {
double d;
unsigned long long ull;
} temp;
printf("sizeof(temp) = %d\n", sizeof(temp));
temp.d = d;
return temp.ull;
}
int sum(int *ptr, int count)
{
int result = 0;
while (--count) {
result += *ptr++;
}
return result;
}
float bit2float(unsigned dword)
{
union {
unsigned a;
float f;
} temp;
temp.a = dword;
return temp.f;
}
double bit2double(unsigned lsdword, unsigned msdword) // argument names reflect little-endianness
{
union {
unsigned a[2];
double d;
} temp;
temp.a[0] = lsdword; // define the bit pattern
temp.a[1] = msdword; // from the arguments
return temp.d; // return that bit pattern interpreted as a double
}
int accum = 0;
int sum(int x, int y)
{
int t = x + y;
accum += t;
return t;
}
int greaterthan10(int x)
{
return (x > 10) ? 1 : 0; // this demonstrates the setg and movzbl opcodes
}
int shift_left2_rightn(int x, int n)
{
x <<= 2; // opcode is shll
x >>= n; // opcode is sarl
return x;
}