表达式

表达式语句是表达式后加;

如hour * 60 + minute;

表达式有值和类型两个基本属性
等号运算符的计算结果是左边的值。多个等号从右到左计算。

如果一个操作数左右两侧各有一个相同优先级的运算符,这个操作数的结合取决于运算符的结合性,相同优先级的运算符的结合性相同。

a=b=c 合法 而(a=b)=c (a=b)不是左值 不合法

函数调用是一种表达式,()运算符是后缀运算符,函数名是操作数,()及其中参数是操作数的后缀

使用math.h加-lm

echo $?可以查看上一条命令的退出状态(return 0)

调用未声明的函数,编译器猜测类型,猜测返回值为int

调用函数时若参数列表为空,且缺乏函数原型,则编译器认为参数类型是void

声明函数时若参数列表为空,属于Old Style C,编译器认为参数类型和个数没有明确指定

//不允许嵌套定义函数

声明也是以;号结尾,这一点和语句类似,但是在语法上声明和语句是有区别的

switch坑

case 1: int i = 10;
 
switch(n) {
	int i = 10;//i未初始化
	case 1:
	//...
}

memberwise initialization
多维数组 或者结构体数组嵌套同理

struct complex z1 = {.y = 4.0};//z1.x=0.0 z1.y=4.0
int count[4]= {[2] = 3};

枚举类型的成员名和变量名在同一空间,而结构体不在。

数组不能相互赋值,也就不能用作函数参数或返回值,但数组类型作右值时,会自动转换成指向数组首元素的指针。

字符串字面量的字符可以用下标访问但不能修改,字符串字面量作右值使用时也自动转换成指针

char c = "Hello, world"[1];

c语言存储数组,一行一行拼成一串,row major

int a[3][2] = {1,2,3,4,5};

-g选项生成文件才可以调试

gcc -g main.c -o main
gdb main
 
list //查看源代码
start //开始
next //一句句执行
step //进入
backtrace //查看栈帧
info local //查看变量
frame //选择栈帧
print 表达式//打印表达式的值
finish //运行到返回
set var 变量=xxx //
display //跟踪显示变量
break //设置断点
continue //运行到断点为止
info breakpoints
 
break 9 if sum != 0
run

异或应用

从异或的真值表可以看出,不管是0还是1,和0做异或保持原值不变,和1做异或得到原值的相反值。可以利用这个特性配合掩码实现某些位的翻转

如果a 1 ^a 2 ^a 3 ^…^a n 的结果是1,则表示a 1 、a 2 、a 3 …a n 之中1的个数为奇数个,否则为偶数个。可用于奇偶校验

由于x^x=0 x^x^y=y 可用于交换变量

//不适用于a=b
*a = *a ^ *b;
*b = *b ^ *a;
*a = *a ^ *b;

sizeof

sizeof是一个很特殊的运算符,它有两种形式:“sizeof 表达式”和“sizeof(类型名)”。

“sizeof 表达式”中的表达式不求值,只推断类型。编译时就能得到

int a[12];
printf("%u\n", sizeof a/sizeof a[0]); //48/4

返回值类型为size_t,定义在stddef.h头文件中,是一种无符号整型

typedef

typedef char array_t[10];
array_t a;