这几天家里实在是太多客人了,环境太嘈杂。
一、运算符
- 使用整数除以整数只能得到整数
- 学习比较运算符号才知道,c99之后才增加的布尔类型,而且布尔类型的本质是整型数字0与1(0假,1真)
- 自增与自减运算符只能对变量有效,对常量无效,(可以理解为常量本来就不可以改)(或者理解为这两个运算符是对空间操作)
- &:相同为1,不同为0
- |:有1为1,有0为0
- ^:不同为1,相同为0
- ~:1的0,0的1
下面是利用运算符写的一个开关案例
#include <stdio.h>
#define FLAG_VISIBLE 0x1 //0001
#define FLAG_TRANSPARENT 0x2 //0010
#define FLAG_RESIZE 0x4 //0100
int main() {
int window_flags = FLAG_VISIBLE | FLAG_RESIZE;//这样就可以得到一个总开关0110
int visible = FLAG_VISIBLE & window_flags;//0000
int resize = FLAG_RESIZE & window_flags;//0100
//这样就可以拿到2个开关,一个是0000,一个是0100
}
-
与<<是移位运算符。(<<1就是×2,>>1就是/2)
- 优先级记不清楚的话,多使用()
二、条件分支语句
- C99之后才引入一个_Bool,msvc中虽然只支持C90,但是也支持_Bool哟<stdbool.h>,定义了一个宏bool,只能为1或者0,所以使用bool类型时候,也就是_Bool,也就是0与1。
- 哪怕是一条语句也最好写上括号,不然嵌套多的时候,不方便观察
三、循环语句
- 案例一
#include <stdbool.h>
#include <stdio.h>
int main() {
#define ADD '+'
#define SUB '-'
#define MULTIPLY '*'
#define DIVIDE '/'
#define REM '%'
int left;
int right;
char operator;
char command;
do {
printf("Please input an expression: \n");
scanf("%d %c %d", &left, &operator, &right);
int result;
switch (operator) {
case ADD:result = left + right;
break;
case SUB:result = left - right;
break;
case MULTIPLY:result = left * right;
break;
case DIVIDE:result = left / right;
break;
case REM:result = left % right;
break;
default:printf("Unsupported operation: %c\n", operator);
return 1;
}
printf("Result: %d\n", result);
printf("Again? Type 'q' for quit: \n");
// puts("Again? Type 'q' for quit: ");
// scanf("%c", &command);
getchar();//为了把回车读走
command = getchar();
printf("%d\n", command);
} while (command != 'q');
}
- 案例二
int sumij = 0;
for (int i = 0, j = 0; i <= 100 && j <= 100; ++i, ++j) {
sumij += i * (i + j);
}
printf("sumij: %d\n", sumij);
- 案例三
// goto
int i = 0;
begin:
printf("%d\n", i);
if (i++ < 5) {
goto begin;
}
四、函数
- 参数列表如果是没有参数传递的话,写void
//这里的void是表示这个函数是不用传递参数进去的,如果是调用时候传递,会报错的
void EmptyParamList(void){}
//这个函数也是不需要传递参数,但是在调用的时候,如果传递参数进去的话,不会报错的
void ALLOWParamList(){}
- 函数原型
#include <stdio.h>
/*
* 1. 函数名
* 2. 函数返回值类型,如果没写,默认为 int
* 3. 函数参数列表,参数类型,和参数的顺序,参数形参名不重要
*/
//原型甚至不用写函数名
int Add(int, int);
void EmptyParamList(void);
int main(void) {
puts("");
EmptyParamList();
int result = Add(1, 2);
printf("result of add: %d\n", result);
return 0;
}
//定义时候并不用写类型
int Add(a,b){
return a+b;
}
void EmptyParamList(void) {
puts("Hello");
}
变量的
- 作用域有{}块作用域、函数作用域、函数原型()中的原型作用域、文件作用域
- 变量也有类型滴,平时我们写的int value = 0;其实是auto int value = 0;表示value的类型是自动的,而装载的值为int型
- 当一个变量内省为static,例如static int value = 0;这个时候这个变量就是全局变量,或者称为文件变量,作用域全局,内存不会因函数退出而销毁
// 静态变量
// 1. 作用域全局,内存不会因函数退出而销毁
// 2. int 初值默认为 0
static int static_var;
// 自动变量
// 1. 函数、块作用域,随着函数和块退出而销毁
// 2. 没有默认初值
int non_static_var;
- 函数的变长参数
#include <stdio.h>
#include <stdarg.h>
void HandleVarargs(int arg_count, ...) {
// 1. 定义 va_list 用于获取我们变长参数
va_list args;
// 2. 开始遍历
va_start(args, arg_count);
for (int i = 0; i < arg_count; ++i) {
// 3. 取出对应参数,(va_list, type)
int arg = va_arg(args, int);
printf("%d: %d\n", i, arg);
}
// 4. 结束遍历
va_end(args);
}
int main(void) {
printf("Hello World\n");
HandleVarargs(4, 1,2,3.0,4);
return 0;
}
五、乱七八糟
- 如果是只输出一个字符串并换行的话,可以使用puts
- 输入可以使用scanf但是需要格式化,使用getchar()就不用
- c99之前不能这样写for(int i = 0; i < 5; i++),只能把int i拿出去,不能在里面声明定义
- 少用goto语法
- 使用<stdlib.h>可以或者生成随机数函数rand(),可以配合传入时间生成真正的种子
- 使用<time.h>里面time(NULL)
- 使用if,else之类的,哪怕是因为只有一条语句而没有写{},也是块作用域