C语言语法入门-基本数据类型
9unk Lv5

基本数据类型和数

算数类型和基本数据类型

算数类型是多种数据类型的统称,大体上可分为两种类型:整数类数据和浮点型数据。
1

字符型、整型和浮点型统称为基本数据类型。

基数

这里的基数指的就是十六进制、十进制、八进制、二进制数。
2

基数转换

基数转换指的就是进制之间的转换
3

整型和字符型

整型和字符型是用来表示限定范围内连续整数的数据类型。

整型分为无符号整数和有符号整数,其数据类型定义分别如下:

1
2
3
int x;	/*x是有符号数*/
signed int y; /*y是有符号数 int 型*/
unsigned int z /*z是无符号数 int 型*/

数据类型汇总

4

头文件 limits.h

C语言编译器在 <limits.h> 文件中以宏定义的形式定义了字符型以及其他整数型所能表示的数值的最小值和最大值。

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
//
// limits.h
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// The C Standard Library <limits.h> header.
//
#pragma once
#define _INC_LIMITS

#include <vcruntime.h>

#pragma warning(push)
#pragma warning(disable: _VCRUNTIME_DISABLED_WARNINGS)

_CRT_BEGIN_C_HEADER

#define CHAR_BIT 8
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
#define UCHAR_MAX 0xff

#ifndef _CHAR_UNSIGNED
#define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX
#else
#define CHAR_MIN 0
#define CHAR_MAX UCHAR_MAX
#endif

#define MB_LEN_MAX 5
#define SHRT_MIN (-32768)
#define SHRT_MAX 32767
#define USHRT_MAX 0xffff
#define INT_MIN (-2147483647 - 1)
#define INT_MAX 2147483647
#define UINT_MAX 0xffffffff
#define LONG_MIN (-2147483647L - 1)
#define LONG_MAX 2147483647L
#define ULONG_MAX 0xffffffffUL
#define LLONG_MAX 9223372036854775807i64
#define LLONG_MIN (-9223372036854775807i64 - 1)
#define ULLONG_MAX 0xffffffffffffffffui64

#define _I8_MIN (-127i8 - 1)
#define _I8_MAX 127i8
#define _UI8_MAX 0xffui8

#define _I16_MIN (-32767i16 - 1)
#define _I16_MAX 32767i16
#define _UI16_MAX 0xffffui16

#define _I32_MIN (-2147483647i32 - 1)
#define _I32_MAX 2147483647i32
#define _UI32_MAX 0xffffffffui32

#define _I64_MIN (-9223372036854775807i64 - 1)
#define _I64_MAX 9223372036854775807i64
#define _UI64_MAX 0xffffffffffffffffui64

#ifndef SIZE_MAX
// SIZE_MAX definition must match exactly with stdint.h for modules support.
#ifdef _WIN64
#define SIZE_MAX 0xffffffffffffffffui64
#else
#define SIZE_MAX 0xffffffffui32
#endif
#endif

#if __STDC_WANT_SECURE_LIB__
#ifndef RSIZE_MAX
#define RSIZE_MAX (SIZE_MAX >> 1)
#endif
#endif

_CRT_END_C_HEADER

#pragma warning(pop) // _VCRUNTIME_DISABLED_WARNINGS

通过调查这些宏的值,就可以判定自己使用的编译器中各数据类型所能表示的数值范围。

代码清单7-1

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
/*程序名:list0701.c*/
/*
显示字符型和整数型数据类型的表示范围
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
puts("该环境下各字符型、整型数值的范围");
printf("char :%d~%d\n", CHAR_MIN, CHAR_MAX);
printf("signed char :%d~%d\n", SCHAR_MIN, SCHAR_MAX);
printf("signed char :%d~%d\n", 0, UCHAR_MAX);

printf("short :%d~%d\n", SHRT_MIN, SHRT_MAX);
printf("int :%d~%d\n", INT_MIN, INT_MAX);
printf("long :%d~%d\n", LONG_MIN, LONG_MAX);

printf("unsigned short :%d~%d\n", 0, USHRT_MAX);
printf("unsigned :%d~%d\n", 0, UINT_MAX);
printf("unsigned long :%d~%d\n", 0, LONG_MAX);

return 0;
}

字符型

char 型是用来保存 “字符” 的数据类型。

对于没有声明 signed 和 unsigned 的char 型,视为有符号类型还是无符号类型,由编译器决定。

代码清单7-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*程序名:list0702.c*/
/*
判断char型有无符号
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{

printf("这个编译器中的char型是");
if (CHAR_MIN)
puts("有符号的。");
else
puts("无符号的。");

return 0;
}

char 类型的数据大小是 CHAR_BIT(8位) 就是一字节。

sizeof 运算符

sizeof 运算符可以判断出所有数据类型的长度,该运算符以字节为单位。

代码清单7-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*程序名:list0703.c*/
/*
显示字符型和整型的长度
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
printf("sizeof (char) = %u\n", (unsigned)sizeof(char));
printf("sizeof (short) = %u\n", (unsigned)sizeof(short));
printf("sizeof (int) = %u\n", (unsigned)sizeof(int));
printf("sizeof (long) = %u\n", (unsigned)sizeof(long));
return 0;
}

sizeof运算符功能是由编译器实现,并未产生相应的汇编代码。

size_t型和typedef 声明

由 sizeof 运算符生成的值的数据类型在 <stddef.h> 头文件中定义的 size_t 型。在许多编译器中用 typedef 声明来定义 size_t 型。

5

size_t 是无符号字符(unsigned)的别称,该类型主要是为了让代码易读。

整型的灵活运用

通常,int 型是程序运行环境中最容易处理并且可以高速运算的数据类型。在有些 sizeof(long) 大于 sizeof(int) 的编译器中,long型的运算比 int 型更耗时。因此只要不处理特别大的数值,还是尽量使用 int 型比较好。

这主要是因为在32位系统中,寄存器的大小和int型都是32位的数据,数据处理起来方便。如果数据类型超过32位或小于32位处理起来就比较麻烦,程序所耗费的时间也就越长。

代码清单7-4

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
/*程序名:list0704.c*/
/*
显示数据类型和变量的长度
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
int na, nb;
double dx, dy;

printf("sizeof(int) = %u\n", (unsigned)sizeof(int));
printf("sizeof(double) = %u\n", (unsigned)sizeof(double));

printf("sizeof(na) = %u\n", (unsigned)sizeof(na));
printf("sizeof(dx) = %u\n", (unsigned)sizeof(dx));

printf("sizeof(na+nb) = %u\n", (unsigned)sizeof(na+nb));
printf("sizeof(na+dy) = %u\n", (unsigned)sizeof(na+dy));
printf("sizeof(dx+dy) = %u\n", (unsigned)sizeof(dx+dy));
return 0;
}

将 sizeof 运算符应用于数组,就可以得到数组整体的大小。

代码清单7-5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*程序名:list0705.c*/
/*
求数组元素的个数
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
int vi[10];
double vd[25];

printf("数组vi的元素个数 = %u\n", (unsigned)(sizeof(vi) / sizeof(vi[0])));
printf("数组vd的元素个数 = %u\n", (unsigned)(sizeof(vi) / sizeof(vd[0])));
return 0;
}

按位操作运算符

位运算符 功能
& 逻辑与
| 逻辑或
^ 逻辑异或
~ 反码

注意:这里要把 “逻辑运算符”(&&、||、!) 和 “按位逻辑运算符” (&、|、~)区分开。

代码清单7-6

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
/*程序名:list0706.c*/
/*
按位运算
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

/*返回整数x中设置的位数*/
int count_bits(unsigned x)
{
int bits = 0;
while (x)
{
if (x & 1U) bits++;
x >>= 1;
}
return bits;
}

int int_bits(void)
{
return count_bits(~0U);
}

void print_bits(unsigned x)
{
int i;
for (i = int_bits() - 1; i >= 0; i--)
putchar(((x>> i) & 1U) ? '1' : '0');
}

int main(void)
{
unsigned a, b;
printf("请输入两个非负整数。\n");
printf("a:"); scanf("%u", &a);
printf("b:"); scanf("%u", &b);

printf("\na = "); print_bits(a);
printf("\nb = "); print_bits(b);
printf("\na & b = "); print_bits(a&b);
printf("\na | b = "); print_bits(a|b);
printf("\na ^ b = "); print_bits(a^b);
printf("\n~a = "); print_bits(a);
printf("\n~b = "); print_bits(~b);
putchar('\n');
return 0;
}

位移运算符

位移运算符 功能
>> 左移运算符
<<

代码清单7-7

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
/*程序名:list0707.c*/
/*
显示对unsigned型的值进行左移和右移后的值
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

/*返回整数x中设置的位数*/
int count_bits(unsigned x)
{
int bits = 0;
while (x)
{
if (x & 1U) bits++;
x >>= 1;
}
return bits;
}

int int_bits(void)
{
return count_bits(~0U);
}

void print_bits(unsigned x)
{
int i;
for (i = int_bits() - 1; i >= 0; i--)
putchar(((x>> i) & 1U) ? '1' : '0');
}

int main(void)
{
unsigned a, b;
printf("请输入非负整数。\n");
printf("a:"); scanf("%u", &a);
printf("位移位数:"); scanf("%u", &b);

printf("\n整数 = "); print_bits(a);
printf("\na左移后的值 = "); print_bits(a<<b);
printf("\na右移后的值 = "); print_bits(a>>b);
putchar('\n');
return 0;
}

整数常量

十进制常量:10、57等等
八进制常量:010、057
十六进制常量:0x10、0x57

整型常量的数据类型

在 limits.h 文件中,整型常量附带 U 和 L 等符号,这些符号称为整型后缀。

  • u/U 表示该整型常量为无符号类型(unsigned)
  • l/L 表示该整型常量为 long 型(long)
  • u/U和l/L 表示整数常量无符号 long 型(unsigned long)

整数的显示

pritnf函数:“%d” 输出十进制数,“%o” 输出八进制数,“%x” 输出十六进制数。

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
/*程序名:list0708.c*/
/*
以十进制、二进制、八进制和十六进制的形式显示0~65535
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

/*返回整数x中设置的位数*/
int count_bits(unsigned x)
{
int bits = 0;
while (x)
{
if (x & 1U) bits++;
x >>= 1;
}
return bits;
}

int int_bits(void)
{
return count_bits(~0U);
}

void print_bits(unsigned x,unsigned n)
{
int i=int_bits();
i=(n<i)?n-1:i-1;
for (; i >= 0; i--)
putchar(((x>> i) & 1U) ? '1' : '0');
}

int main(void)
{
unsigned i;
for (i = 0; i <= 65535U; i++)
{
printf("%5u", i);
print_bits(i, 16);
printf("%06o %04x\n", i, i);
}
return 0;
}

数据溢出和异常

溢出

  1. 有符号数运算的溢出
  2. 无符号数运算的溢出

异常

在算数运算中常见的除法异常。

算数运算中的溢出和异常汇编中都学过,就不再去重复写代码验证了。

浮点型

浮点型数据类型

浮点型用来表示带有小数部分的实数。浮点型有以下3中类型。

  • float:单精度浮点型。
  • double:双精度浮点型。
  • long double:长双精度浮点型。

代码清单7-9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*程序名:list0709.c*/
/*
表示浮点整数变量的值和宽度。.
*/

int main(void)
{
//在 visual 2022 中double和long double 的所能表示的精度都是一样的,所以y和z的值相同。
float x=123456789012345678901234567890.0;
double y=123456789012345678901234567890.0;
long double z=123456789012345678901234567890.0;

printf("x = %f\n", x);
printf("y = %lf\n", y);
printf("z = %llf\n", z);

//各浮点数据类型宽度
printf("单精度浮点型宽度:%d\n双精度浮点型宽度:%d\n长双精度浮点型宽度:%d", sizeof(float), sizeof(double), sizeof(long double));
return 0;
}

long double 类型不是原始的C标准类型。C99中才添加了这种类型。而在C99及后续规范中,该类型的规定也不详细,只是要求long double 类型在精度上需要不少于double的精度。于是出现了有的编译器不支持long double,而支持的编译器在实现上也有区别,目前常见的long double有占8字节,10字节,12字节和16字节四种,单输出格式都是相同的 %llf。

浮点数转换为二进制原理

浮点数转换为二进制数据分为如下几步:

  1. 将十进制的浮点数转换为二进制浮点数

浮点数的二进制值由三个部分组成:符号位(1位) 指数位(8位) 尾数位(23位)

  1. 根据浮点数的正负值确定符号位
  2. 移动小数点的位置确定指数部分
  3. 将小数点后的位放在尾数部分

1、将十进制浮点数以二进制浮点数表示

将十进制浮点数的整数部分循环除以2,取余数并倒序排序作为整数部分二进制值。
将小数部分乘以2,取整数作为小数部分的二进制值。

案例:十进制小数 3.1 转换为二进制形式

整数部分:

1
2
3/2=1...1
1/2=0...1

小数部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
0.1*2=0.2...0
0.2*2=0.4...0
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1
0.2*2=0.4...0
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1
0.2*2=0.4...0
0.4*2=0.8...0
0.8*2=1.6...1
0.6*2=1.2...1

最终结果:11.0001100010001100011000

因为小数部分的计算丢弃了小数点后面的值因此这也就导致了小数的计算结果并不准确,而计算机存储的二进制又有限,这就导致计算机在运算浮点数的结果都是近似值。

2、将二进制浮点数转换成二进制数据

符号位:如果是正数值为0,负数为1
指数位:左移或右移小数点,浮点数的二进制表示形式的整数位只有1位,且值必须是1。指数位默认值是127,如果是左移 “指数位=【127+左移位数】”,如果是右移“指数位=【127-右移位数】”
尾数位:将二进制表示形式的小数点后面的值作为尾数。

根据以上规则得出结果小数3.1存储的二进制值如下:
符号位:0
指数位:11.0001100010001100011000 = 1.10001100010001100011000*2^1;127+1=128=1000 0000
尾数位:10001100010001100011000

最终结果:0 10000000 1000110011001100110010 = 0x4046 6666

单精度浮点数尾数是23位,双精度浮点数尾数位是52位。

代码实现

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
164
165
166
167
168
169
170
171
172
/*程序名:list0709a.c*/
/*
写一个输出浮点数存储二进制值的函数,并且能够处理,正负浮点数和整数部分为0的浮点数
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


/*----------------------------------------------------------------
函数名:WriteBin
功能:输出n个字节二进制值
参数1:变量x
参数2:要输出的字节数
返回值:无
------------------------------------------------------------------*/
void WriteBin(int x,const int n)
{
char* str = "%c"; //printf 参数1
int* addr = &x; //变量x指针

/*
代码逻辑:
1. 外循环,按字节数来循环,因为数据是小端存储,因此指针需要从高地址到低地址,因此每次循环指针减一(即dec esi)
2. 内循环,循环八次并判断输出相应的二进制数(即输出一个字节的二进制)。
*/
__asm
{
xor ebx,ebx
mov ecx, n //外循环次数(字节数)
mov esi, addr
add esi, n //指针地址
WriteBin1:
push ecx
dec esi
mov bl, byte ptr[esi]
mov ecx,8 //内循环次数
ByteToBits1:
push ecx
shl bl,1
jnc ByteToBits2
mov eax, '1'
jmp ByteToBits3
ByteToBits2:
mov eax, '0'
ByteToBits3:
push eax
push str
call printf
add esp,8
pop ecx
loop ByteToBits1
pop ecx
loop WriteBin1
}
}

void floatB(float x)
{
/*强制将浮点数转换为整数,计算浮点指数,这里使用abs函数将参数转换为整数绝对值*/
int a = abs(x);
/*打印指数*/
int b = 127;
/*存储整数部分*/
char mantissa[26] = { 0 };
/*代表指数*/
int index = 0;
/*存储小数部分*/
float c = 0;
/*打印浮点数的十六进制数*/
int* Ufloat = &x;


int i, n;
puts("浮点数转换为二进制表示形式:");
/*先算整数部分:整数部分/2,取余数,直到商为0*/
//a = abs(x);
for (int k = 0; a != 0; k++)
{
/*计算商和余数*/
mantissa[k] = a % 2;
a /= 2;
index = k;
}
/*倒序打印整数部分*/
for (int k = index; k >= 0; k--)
{
printf("%d", mantissa[k]);
}
printf(".");

/*打印小数结果*/
a = abs(x); //计算整数部分,变量a被修改了,这里重置一下
if (x > 0)
{
c = x - a;
}
else
{
c = -(x + a);
}

for (int k = index + 1; k < 24; k++)
{
c *= 2;
printf("%d", (int)c);
mantissa[k] = c;
if (c >= 1)
{
c -= 1;
}
}


puts("\n\n内存中存储的值:");
puts("符号位---指数位---尾数位");
/*符号位*/
if (x > 0)
{
printf(" 0 ");
}
else
{
printf(" 1 ");
}

/*指数位*/
a = abs(x);
/*如果整数为0,index=-1*/
if (a == 0)
{
index -= 1;
for (int j = 1; mantissa[j] == 0; j++)
{
index -= 1;
}
}


WriteBin(127 + index, 1);
printf(" ");


/*尾数位*/
if (index < 0)
{
for (int k = 0; k < 24; k++)
{
printf("%d", mantissa[k]);
}
}
else
{
for (int k = 1; k < 24; k++)
{
printf("%d", mantissa[k]);
}
}

printf("\n\n浮点表示法:%.16f", x - 0.00000000000000001);
printf("\n\n浮点数的十六进制值:%x", Ufloat[0]);

}

int main(void)
{
float x = 3.1;

floatB(x);
return 0;
}

<math.h> 头文件

C语言提供了基本的数学函数来支持科学计算。<math.h>文件中包含了这些函数的声明。

代码清单7-10

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
/*程序名:list0710.c*/
/*
求两点间的距离
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*---求出点(x1,y1)和点(x2,y2)之间的距离---*/
double dist(double x1,double y1,double x2,double y2)
{
return sqrt(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
}

int main(void)
{
double x1, y1;
double x2, y2;

printf("求两点间的距离。\n");
printf("点1...X坐标"); scanf("%lf", &x1);
printf(" Y坐标"); scanf("%lf", &y1);
printf("点2...X坐标"); scanf("%lf", &x2);
printf(" Y坐标"); scanf("%lf", &y2);

printf("两点之间的距离为%f。\n", dist(x1, y1, x2, y2));
return 0;
}

循环的控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*程序名:list0711.c*/
/*
以0.01为单位从0.0递增至1.0的循环
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
float x;
for (x = 0.0; x <= 1.0; x += 0.01)
{
printf("x=%f\n", x);
}
return 0;
}

这里因为浮点运算只能取近似值的关系,导致最终结果为0.999999,并不能达到0.1

代码清单7-12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*程序名:list0712.c*/
/*
以0.01为单位从0.0递增至1.0的循环(用整数控制)
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
int i;
float x;
for (i = 0; i <= 100; i++)
{
x = i / 100.0;
printf("x=%f\n", x);
}
return 0;
}

这里不以浮点数作为循环变量,而是以运算方式(整数/浮点数)来取得运算结果。

运算和运算符

6

运算符优先级不需要考虑,要优先运算哪个就在那里加个小括号。

数据类型转换

7
8

总结

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
/*程序名:summary.c*/
/*
浮点数加法运算
*/

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
int i, no;
float value;
float sum = 0.0f;

puts("对浮点数进行多次加法运算。");
printf("值"); scanf("%f", &value);
printf("次数:"); scanf("%d", &no);

for (i = 0; i < no; i++)
sum += value;
printf("加法运算的结果是%f。\n", sum);
return 0;
}

练习

练习7-1

9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*程序名:lx7-1.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
int n;
printf("%d\n", sizeof 1 );
printf("%d\n", sizeof +1 );
printf("%d\n", sizeof -1 );
printf("%d\n", sizeof(unsigned)-1);
printf("%d\n", sizeof(double)-1);
printf("%d\n", sizeof((double)-1));
printf("%d\n", sizeof n+2 );
printf("%d\n", sizeof(n + 2));
printf("%d\n", sizeof(n + 2.0));

return 0;
}

练习7-2

10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*程序名:lx7-2.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
unsigned int n = 4;

printf("n左移2位的值:%d,n乘以2的2次幂的值:%d\n", n << 2, n * 4);
printf("n右移2位的值:%d,n除以2的2次幂的值:%d\n", n >> 2, n / 4);
return 0;
}

练习7-3

11

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
/*程序名:lx7-3.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

unsigned rrotate(unsigned x,int n)
{
return x >> n;
}

unsigned lrotate(unsigned x, int n)
{
return x << n;
}

int main(void)
{
unsigned int x = 4;
int n = 2;

//rrotate(x, n);
//lrotate(x, n);
printf("%d左移%d位的值:%d\n", x,n,lrotate(x, n));
printf("%d右移%d位的值:%d\n", x,n,rrotate(x, n));
return 0;
}

练习7-4

12

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
/*程序名:lx7-4.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

//将 pos 位置 1
unsigned set(unsigned x,int pos)
{
//pos1 将pos位置为1
int pos1 = (1 << (pos - 1));
//这里用的或运算,因为 1^1=0 结果会出现改变。
//判断x的pos位是否为1
int n = x & pos1;
//如果n!=pos1,说明该位为0,需要置1
if (n != pos1)
{
return x | pos1;

}
//反之,返回原值
return x;
}

//将 pos 位置 0
unsigned reset(unsigned x, int pos)
{
//pos1 将pos位置为1
int pos1 = (1 << (pos - 1));
int n = x & pos1;
//0^1=1;1^1=0,为了防止 pos 改为1的情况,需要做好判断。
//如果n==pos1,说明该位为1,需要做置0
if (n == pos1)
{
return x ^ pos1;
}
//反之,返回原值
return x;

}

unsigned inverse(unsigned x, int pos)
{
//直接异或得出取反结果
int pos1 = (1 << (pos - 1));
return x ^ pos1;

}


int main(void)
{
printf("%d",set(13, 1));
return 0;
}

练习7-5

13

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
/*程序名:lx7-5.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

//将 pos 位到 (pos+n-1) 位的n位置 1
unsigned set_n(unsigned x,int pos,int n)
{
int a = 0;
int pos1 = 0;
int buffer = x;
for (int i = 1;i<=n; i++)
{
//pos1 将pos位置为1
pos1 = (1 << (pos - i));
//这里用的或运算,因为 1^1=0 结果会出现改变。
//判断x的pos位是否为1
a = x & pos1;
//如果n!=pos1,说明该位为0,需要置1
if (a != pos1)
{
buffer |= pos1;

}
}
//反之,返回原值
return buffer;
}




//将 pos 位到 (pos+n-1) 位的n位置 0
unsigned reset_n(unsigned x, int pos,int n)
{
int a = 0;
int pos1 = 0;
int buffer = x;
for (int i = 1; i <= n; i++)
{
//pos1 将pos位置为1
pos1 = (1 << (pos - i));
a = buffer & pos1;
//0^1=1;1^1=0,为了防止 pos 改为1的情况,需要做好判断。
//如果n==pos1,说明该位为1,需要做置0
if (a == pos1)
{
buffer ^= pos1;
}
}
return buffer;

}

unsigned inverse_n(unsigned x, int pos,int n)
{
int a = 0;
int pos1 = 0;
int buffer = x;
for (int i = 1; i <= n; i++)
{
//直接异或得出取反结果
int pos1 = (1 << (pos - i));
buffer ^= pos1;
}

return buffer;

}


int main(void)
{
printf("%d", inverse_n(128,4,4));
return 0;
}

练习7-6

14

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
/*程序名:lx7-6.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

void flow(unsigned x, unsigned y)
{
unsigned sum = x + y;
if (sum < x|sum < y)
{
printf("CF=1");
}
else
{
printf("CF=0");
}
}


int main(void)
{
flow(4294967295, 10);
return 0;
}

练习7-7

15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*程序名:lx7-7.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float a;
double b;
long double c;
//float 精确到6位小数
printf("请输入float类型的变量:"); scanf("%f", &a);
//double 精确到15位小数
printf("请输入double类型的变量:"); scanf("%lf", &b);
//long double 精确到15位小数
printf("请输入long double类型的变量:"); scanf("%lf", &c);

printf("%f \n%.15f \n%.15f", a, b, c);
return 0;
}

练习7-8

16

1
2
3
4
5
6
7
8
9
10
11
12
/*程序名:lx7-8.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
printf("%d \n%d \n%d", sizeof(float), sizeof(double), sizeof(long double));
return 0;
}

练习7-9

17

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*程序名:lx7-9.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(void)
{
float a = 0;
printf("请输入正方形面积(实数):"); scanf("%f", &a);
printf("正方形的边长是%f", sqrt(a));
return 0;
}

练习7-10

18

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*程序名:lx7-10.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int i;
float x;
for (i=0,x = 0.0; x <= 1.0&&i<=100; x += 0.01,i++)
{
printf("x=%f ", x);
x = i / 100.0;
printf("x=%f\n", x);
}
return 0;
}

练习7-11

19

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*程序名:lx7-11a.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float x,y=0.0;
for (x = 0.0; x <= 1.0; x += 0.01)
{
y += x;
printf("x=%f\n", x);
}
printf("x递增后所有值的累计:%f\n", y);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*程序名:lx7-11b.c*/


#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int i;
float x,y=0.0;
for (i = 0; i <= 100; i++)
{
x = i / 100.0;
y += x;
printf("x=%f\n", x);
}
printf("x递增后所有值的累计:%f\n", y);

return 0;
}
  • 本文标题:C语言语法入门-基本数据类型
  • 本文作者:9unk
  • 创建时间:2023-06-13 13:58:00
  • 本文链接:https://9unkk.github.io/2023/06/13/c-yu-yan-yu-fa-ru-men-ji-ben-shu-ju-lei-xing/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!