00main.c
int main(void)
{
return 0;
}
这几行构成了main函数定义的起始部分, 每个C程序都必须有一个main函数, 因为它是程序执行的起点
关键字int表示函数返回一个整形值, 关键字void表示函数不接受任何参数
main函数的函数体包含左花括号和与之相匹配的右花括号之间的任何内容
编译环境: Ubuntu 12.04 gcc version 4.6.3
gcc -c main.c --> 编译单个C源文件, 会产生一个目标文件: main.o
gcc main.o -o main --> 链接这个目标文件, 指定输出的可执行文件名叫做main(不指定的话会默认生成a.out)
gcc main.c --> 这样一步到位也可以得到可执行文件a.out
C语言的编译步骤:
hello.c的编译
1. gcc -E hello.c -o hello.i == gcc -E hello.c > hello.i (得到预处理之后的文件 hello.i)
预处理, 调用预处理器cpp
2. gcc -S hello.c -o hello.s == gcc -S hello.i -o hello.s (得到汇编文件 hello.s)
编译, 调用编译器cc1
3. gcc -c hello.c -o hello.o == gcc -c hello.s -o hello.o (得到目标文件 hello.o)
汇编, 调用汇编器as
4. gcc hello.c -o hello == gcc hello.o -o hello (得到可执行文件 hello)
链接, 调用链接器ld
01hello_world.c
#include
int main(void)
{
printf("hello world!\n");
return 0;
}
第一行代码表示将stdio.h标准输入输出头文件包含到源代码文件中,
stdio.h文件定义和包含有各种库函数的声明, printf就是其中一个.
printf是C语言中最常用的格式化输出函数, 用户通过向printf函数传递各种参数,
printf将其转化成字符串, 最终在终端上输出.
运行结果:
hello world!
02basic_type.c
#include
int main(void)
{
char ch = 0;
short sh = 0;
int i = 0;
long l = 0;
long long ll = 0;
float f = 0.0;
double d = 0.0;
long double ld = 0.0;
printf("sizeof char: %u\n", sizeof(ch));
printf("sizeof short: %u\n", sizeof(sh));
printf("sizeof int: %u\n", sizeof(i));
printf("sizeof long: %u\n", sizeof(l));
printf("sizeof long long: %u\n", sizeof(ll));
printf("sizeof float: %u\n", sizeof(f));
printf("sizeof double: %u\n", sizeof(d));
printf("sizeof long double:%u\n", sizeof(ld));
return 0;
}
基本类型 (修饰符 signed unsigned)
char, short, int, long, long long
float, double, long double
复合类型 数组和指针
构造类型 结构体 联合体/共用体 枚举
sizeof 是运算符
sizeof(type) --> 类型就要加括号
sizeof var --> 变量的话, 可加可不加
运行结果:
sizeof char: 1
sizeof short: 2
sizeof int: 4
sizeof long: 4
sizeof long long: 8
sizeof float: 4
sizeof double: 8
sizeof long double:12
03literal.c
#include
int main(void)
{
int a = 97;
char ch = 'a';
double d = 3.14e2;
double d2 = -3.14e-2;
printf("ch = %c\n", ch);
printf("ch = %d\n", ch);
printf("a = %d\n", a);
printf("a = %#o\n", a); // 表示八进制输出, 0开头
printf("a = %#x\n", a); // 表示十六进制输出, 0x开头
printf("d = %lf\n", d);
printf("d2 = %lf\n", d2);
printf("d2 = %8.3lf\n", d2);
printf("d2 = %-8.3lf\n", d2);
printf("d2 = %e\n", d2);
return 0;
}
整型常量(修饰符: U, L):
decimal: 3, -4, 123
hex: 0x1a, -0x1f
octal: 076, -025
浮点常量(默认为double类型):
3.14
3.14e2
3.14e-2
-3.14e-2
字符常量: 'a', 'b', 'c'
字符串常量: "asdfg"
运行结果:
ch = a
ch = 97
a = 97
a = 0141
a = 0x61
d = 314.000000
d2 = -0.031400
d2 = -0.031
d2 = -0.031
d2 = -3.140000e-02
04scanf.c
#include
int main(void)
{
int a = 0, b = 3;
printf("input two intergers: ");
// & 是一个运算符, 表示取变量a的地址, 再传给scanf
scanf("%d %d", &a, &b);
printf("your inputed: a = %d, b = %d\n", a, b);
return 0;
}
运行结果:
input two intergers: 22 44
your inputed: a = 22, b = 44
05arithmetic_operator.c
#include
int main(void)
{
double x, y, z;
double ret;
printf("input x, y, z: ");
scanf("%lf %lf %lf", &x, &y, &z);
ret = 3*x + 4*y - 5*z;
printf("3x + 4y - 5z = %lf\n", ret);
int r = 10 % 3;
printf("remainder = %d\n", r);
r = 10 / 3;
printf("quotient = %d\n", r);
printf("r++ = %d\n", r++);
printf("++r = %d\n", ++r);
printf("--r = %d\n", --r);
printf("r-- = %d\n", r--);
return 0;
}
算数运算符:
+ - * / % ++ --
运行结果:
input x, y, z: 2.3 5.6 -3.9
3x + 4y - 5z = 48.800000
remainder = 1
quotient = 3
r++ = 3
++r = 5
--r = 4
r-- = 4
06relational_operator.c
#include
int main(void)
{
int a = 3, b = 5;
int ret;
ret = a < b;
printf("ret = %d\n", ret);
ret = a <= b;
printf("ret = %d\n", ret);
ret = a > b;
printf("ret = %d\n", ret);
ret = a >= b;
printf("ret = %d\n", ret);
ret = a == b;
printf("ret = %d\n", ret);
ret = a != b;
printf("ret = %d\n", ret);
return 0;
}
关系运算符
< <= > >= == !=
运行结果:
ret = 1
ret = 1
ret = 0
ret = 0
ret = 0
ret = 1
07logical_operator.c
#include
int main(void)
{
int a = 3, b = 5;
int ret;
ret = (a != b) && (a == b);
printf("ret = %d\n", ret);
ret = (a != b) || (a == b);
printf("ret = %d\n", ret);
ret = !(a < b);
printf("ret = %d\n", ret);
return 0;
}
逻辑运算符
! --> logic not
&& --> logic and
|| --> logic or
运行结果:
ret = 0
ret = 1
ret = 0
08bit_operator.c
#include
int main(void)
{
int a = 3, b = 5;
int ret = 0;
ret = a & b;
printf("ret = %d\n", ret); // 1
ret = a | b;
printf("ret = %d\n", ret); // 7
// 按位异或, 相异为1, 相同为0
ret = a ^ b;
printf("ret = %d\n", ret); // 6
ret = ~a; // sum = a + ret, ret = sum - a
printf("ret = %d\n", ret); // ret = sum - a = -1 - 3 = -4
printf("ret = %u\n", ret); // ret = sum - a = 4294967295 - 3 = 4294967292
// 左移, 低位补0
a = 7;
ret = a << 2; // 相当于乘以4
printf("ret = %d\n", ret); // 28
unsigned int u = -1;
printf("u = %u\n", u);
printf("u = %d\n", u);
// 右移
// unsigned 类型变量, 高位补0
ret = u >> 2; // 高位补0就是正数了, 所以用%d输出就可以了
printf("ret = %d\n", ret);
// 右移
// signed 类型变量, 视最高位决定补0还是补1
a = -1;
ret = a >> 2; // -1的最高位是1, 右移就补1, 存的还是32个1, 所以用%d输出还是-1
printf("ret = %d\n", ret);
a = 15;
ret = a >> 2; // 15的最高位是0, 所以右移是补0
printf("ret = %d\n", ret);
return 0;
}
位运算符:
~ : 按位取反
& : 按位与
| : 按位或
^ : 按位异或
<< : 左移; >> : 右移
0 ^ 1 ^ 0 --> 1
0 ^ 1 ^ 1 --> 0
int a, b;
a ^ b ^ a ==> b // 公式1
a ^ b ^ b ==> a // 公式2
所以交换两个int型变量,有一方法:
a = a ^ b; // a 和 b 的异或值先保存在 a 身上
b = a ^ b; // 这里相当于 b = (a ^ b) ^ b, 按照公式2, 此处相当于 b = a, 即把 a 赋给了 b
a = a ^ b; // 由上一句可知 b 得到了原先 a 的值, 所以这里相当于 a = (a ^ b) ^ a, 按照公式2, 此处相当于 a = b, 即把 b 赋给了 a
运行结果:
ret = 1
ret = 7
ret = 6
ret = -4
ret = 4294967292
ret = 28
u = 4294967295
u = -1
ret = 1073741823
ret = -1
ret = 3
09condition_operator.c
#include
int main(void)
{
int a = 3, b = 5;
int min = 0;
min = a < b ? a : b;
printf("min of %d and %d is %d\n", a, b, min);
return 0;
}
条件运算符:
运行结果:
min of 3 and 5 is 3
10comma_operator.c
#include
int main(void)
{
int a, b, c;
int ret;
ret = a = 3, b = 4, c = 5; // ret 得到了 a 的值
printf("a = %d b = %d c = %d, ret = %d\n", a, b, c, ret);
ret = (a = 3, b = 4, c = 5);// ret 得到了最后 c 的值
printf("a = %d b = %d c = %d, ret = %d\n", a, b, c, ret);
return 0;
}
逗号运算符
运行结果:
a = 3 b = 4 c = 5, ret = 3
a = 3 b = 4 c = 5, ret = 5
11type_cast_1.c
#include
int main(void)
{
int a = 3;
double b = 3.14;
int reti = 0;
double retd = 0.0;
// 隐式类型转换, b 被转了
reti = a + b;
printf("reti = %d\n", reti);
// 隐式类型转换, a 被转了
retd = a + b;
printf("retd = %lf\n", retd);
// 强制类型转换
retd = a + (int)b; // b被强转, 只在本次生效
printf("retd = %lf\n", retd);
return 0;
}
运行结果:
reti = 6
retd = 6.140000
retd = 6.000000
12type_cast_2.c
#include
int main(void)
{
unsigned char uch = -1;
char ch = -1;
int a = 385; // 1_10000001
int ret;
// unsigned 类型, 补0扩展
ret = uch;
printf("ret = %d\n", ret); // 255
// signed 类型, 视最高位决定补0扩展还是补1扩展
ret = ch;
printf("ret = %d\n", ret); // -1
printf("ret = %u\n", ret); // 4294967295
ch = 127;
ret = ch;
printf("ret = %d\n", ret); // 127
printf("ret = %u\n", ret); // 127
printf("\n");
// 截断
// 先截断, 再视上下文解释.
ch = a; // ch在计算机存的是10000001(补码, 需转为原码方可看出数值是多少) --> 最高位是1 --> 还原成原码得减1再取反 --> 01111111 --> 127
printf("ch = %d\n", ch);
printf("ch = %u\n", ch); // ch的最高位是1, 按1扩展, ch = 11111111_11111111_11111111_10000001
printf("\n");
// 溢出
unsigned char uch1 = 253, uch2 = 255;
ret = uch1 + uch2;
printf("ret = %d\n", ret);
uch1 = 258, uch2 = 255;
ret = uch1 + uch2;
printf("ret = %d\n", ret);
return 0;
}
运行结果:
ret = 255
ret = -1
ret = 4294967295
ret = 127
ret = 127
ch = -127
ch = 4294967169
ret = 508
ret = 257
exercise1.c
#include <stdio.h>
int main(void)
{
int i = 0, j = 0;
for(i = 1; i < 10; i++)
{
for(j = 1; j <= i; j++)
{
printf("%dx%d=%02d ", j, i, i*j);
}
printf("\n");
}
printf("\n");
for(i = 9; i > 0; i--)
{
for(j = 1; j <= i; j++)
{
printf("%dx%d=%02d ", j, i, i*j);
}
printf("\n");
}
return 0;
}
练习1: 打印 9 x 9 乘法表
运行结果:
1x1=01
1x2=02 2x2=04
1x3=03 2x3=06 3x3=09
1x4=04 2x4=08 3x4=12 4x4=16
1x5=05 2x5=10 3x5=15 4x5=20 5x5=25
1x6=06 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7=07 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8=08 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9=09 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
1x9=09 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
1x8=08 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x7=07 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x6=06 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x5=05 2x5=10 3x5=15 4x5=20 5x5=25
1x4=04 2x4=08 3x4=12 4x4=16
1x3=03 2x3=06 3x3=09
1x2=02 2x2=04
1x1=01
exercise2.c
#include
int main(void)
{
int a = 58, b = 87;
int temp = 0;
printf("before: a = %d, b = %d\n", a, b);
temp = a;
a = b;
b = temp;
printf("after: a = %d, b = %d\n", a, b);
printf("\n");
a = 58, b = 87; // 此法可能溢出
printf("before: a = %d, b = %d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("after: a = %d, b = %d\n", a, b);
printf("\n");
a = 58, b = 87;
printf("before: a = %d, b = %d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("after: a = %d, b = %d\n", a, b);
return 0;
}
练习2: 交换整形变量, 方法越多越好
运行结果:
before: a = 58, b = 87
after: a = 87, b = 58
before: a = 58, b = 87
after: a = 87, b = 58
before: a = 58, b = 87
after: a = 87, b = 58
exercise3.c
#include
int main(void)
{
unsigned int a = 0;
int i = 0;
printf("input the number: ");
scanf("%u", &a);
for(i = 31; i >= 0; i--)
{
(a & (1<putchar('1') : putchar('0');
if((i != 0) && (i%8 == 0))
putchar('_');
}
putchar('\n');
return 0;
}
练习3: 打印无符号整数的二进制位
运行结果:
input the number: 259
00000000_00000000_00000001_00000011
be careful:
unsigned int i = 0;
for(i = 31; i >= 0; i--)
{
printf("infinite loop\n"); // 无限循环
}
unsigned char j = 0;
for(j = 0; j <= 255; j++)
{
printf("infinite loop\n"); // 同理, 无限循环
}