数组的代码演示:
数组作为函数参数会退化为指针
#include <stdio.h>
void func(int* num) {
printf("func: ");
printf("sizeof(num) = %lu\n", sizeof(num));
return ;
}
int main() {
int arr[100] = {}, n;
printf("sizeof(arr) = %lu\n", sizeof(arr));
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", arr + i);
}
func(arr);
return 0;
}
函数里接收的数组,与原数组不是同一个东西,函数里的形参本质上是一个指针
二维数组传参:
void func(int **num) { // int **num是错误的
}
void func(int num[100][20]) {
}
void func(int num[][20]) {
}
void func(int (*num)[20]) {
// int * 指向一个 int [20]
}
int main() {
int arr[100][20] = {};
func(arr);
return 0;
}
int **num = arr; 报警告是因为地址的类型不匹配。
因为:
int arr[100][20] = {0};
int **num = (int **)arr;
arr[%p]与arr+1[%p]相差20*4B的大小,但是
num[%p]与num[%p]相差8B,地址的大小。
因为int *(*num)是跟着类型的。
外在表现形式是不同的。
三维数组传参:
void func(int ***num) { // int ***num是错误的
}
void func(int num[100][20][10]) {
}
void func(int num[][20][10]) {
}
void func(int (*num)[20][10]) {
// int * 指向一个 int [20][10]
// 最常用
}
int main() {
int arr[100][20][10] = {};
func(arr);
return 0;
}
维度至多只能省略第一个维度
--------------------------------------------
宏作用:文本替换,不做计算
定义符号常量:
#define PI 3.1415926
#define MAX_N 10000
定义傻瓜表达式:不需要加 { }
#define MAX(a, b) (a) > (b) ? (a) : (b)
#define S(a, b) a * b
定义代码段:需要加 { }
#define P(a) { \
printf("%d\n", a); \
}
定义代码段时,如果{}外面加了(),即({}),
小括号的作用是:变成表达式,获取返回值
C语言预定义的宏:
__DATA__ 替换成编译时的日期:Mmm dd yyyy。
__TIME__ 替换成编译时的时间:hh:mm:ss
__LINE__ 替换当前代码的行号
__FILE__ 替换成当前.c的文件名
打印函数信息的宏:(以下3个是非标准宏,所有OS并非通用)
__func__ linux标准
__FUNC__ windows标准
__PRETTY_FUNCTION__
还有很多其他的预定义宏需要自己学习提升
------------------------------------------------
条件式编译:(用于代码剪裁,增加可移植性)
#ifdef DEBUG 是否 定义了 DEBUG宏
#ifndef DEBUG 是否 没定义 DEBUG宏
// 用于版本号之类的
#if MAX_N == 5 宏MAX_N是否等于5
#elif MAX_N == 4 否则宏MAX_N是否等于4
#else
#endif 使用条件式编译,末尾必须加#endif
编译期检查:语法分析、词法分析、语义分析
链接:将所有的.o文件整合成a.out
工业开发:多文件“链编”
随堂练习:实现没有BUG版的MAX(a, b)宏返回a b二者中的最大值,需要通过如下测试:
MAX(2, 3) 3
5 + MAX(2, 3) 8
MAX(2, MAX(3, 4)) 4
MAX(2, 3 > 4 ? 3 : 4) 4
MAX(a++, 6) // a的初始值为7,函数返回值为7,a的值变为8
#include <cstdio>
#define MAX(a, b) ({ \
__typeof(a) x, y; \
x = a; y = b; \
(x) > (y) ? x : y; \
})
//#func表示将读入的MAX(2,3)字符串化
#define P(func) { \
printf("%s = %d\n", #func, func); \
}
int main() {
int a = 7;
P(MAX(2, 3));
P(5 + MAX(2, 3));
P(MAX(2, MAX(3, 4)));
P(MAX(2, 3 > 4 ? 3 : 4));
P(MAX(a++, 6));
P(a);
return 0;
}
vim矩形删除:先两下esc 然后Ctrl+V,上下左右选中,最后 dd 删除
vim批量行添加:Ctrl+V,上下左右选中插入的行,然后按大写的I,进行输入,输入结束两下esc
-----------------------------------------------
宏定义其他冷门、重点知识
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x
x##y表示什么?表示x连接y,举例说:
int n = Conn(123,456); 结果就是n=123456;
char* str = Conn("asdf","adf")结果就是 str = "asdfadf";
#@x,其实就是给x加上单引号,结果返回是一个constchar。
举例说:
char a = ToChar(1);结果就是a='1';
做个越界试验char a = ToChar(123);结果是a='3';
但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015:too many characters in constant :P
#x是给x加双引号
char* str = ToString(123132);就成了str="123132";
如果有#define FUN(a,b) vo##a##b()那么FUN(idma,in)会被替换成void main()