https://cplusplus.com/reference/clibrary/
函数必须先定义后调用,所以main要放在最后
函数不能嵌套定义,没有闭包函数的概念
形参变量只有在函数被调用时才会分配内存,调用结束后,立即释放内存,所以形参变量之后在函数内部有效
实参可以是常量、变量、表达式、函数等,无论实参时何种类型的数据,在调用函数时都必须有确定的值
实参和形参在数量上、类型上,顺序上必须严格一致,可以自动进行类型转换
实参、形参可以同名,单他们之间是相互独立的,互不影响。(实参在函数外部有效,形参在函数内部有效)
有返回值 typename func(){return val};
无返回值 void func(){}; 可以不写return
函数f1调用函数f2的时候,函数f1通过参数给函数f2传递了另一个函数f3的指针,在函数f2执行的过程中,函数f2调用了函数f3,这个过程就叫做callback
这个先被当做指针传入,后面又被回调的函数f3就是回调函数
type func(type1 param1,type2 param2);
type func(type1,type2); // 声明时可以不写形参,只写数据类型
函数声明写在头文件中,链接阶段找到函数体
一般函数都放在源文件中,这些源文件都已经提前编译好了,并以静态链接库或动态链接库的形式存在
全局变量存储在内存分区中的全局数据区,这个区域中的数据在程序载入内存后被初始化为0,也就是全局变量默认的初始值为0
全局变量修改后,会影响其他函数
全局变量的作用范围不是从变量定义到该文件结束,在其他文件中也有效
static
静态变量,仅限于当前文件内部调用
extern
外部存储变量,用于声明在当前文件中将要用到的其他文件中的变量
局部变量根据C++标准的不同,可能是随机值,也可能是0
main()
函数中定义的变量也是局部变量
auto
自动变量,离开定义的函数立即消失
register
寄存器变量,离开定义的函数立即消失
static
静态变量,离开定义的函数仍然存在
常量可以是任何基本的数据类型,可以理解为字面量
常量的值在定义后 不能进行修改
const
修饰的变量,也可以是常量
全局变量和局部变量
全局变量:的作用域是全部的文件,包括.c和.h文件
全局变量的作用范围不是从变量定义到该文件结束,在其他文件中也有效
{code...}
单独的代码块也是一个作用域
static 全局变量
作用域变成了当前文件
for
,while
会引入新的作用域,(块级作用域,C/cpp的特性)
形参-实参相当于赋值操作
不同于下面的参数引用机制
对于数值型
赋值修改,并不会改变内存地址
inplace
操作不会改变内存地址(inplace操作也包括自增自减)
#include
int main()
{int a=1;printf("%p\n",&a); // 000000000061FE1Ca=100;printf("%p\n",&a); // 000000000061FE1C,地址不变a+=100printf("%p\n",&a); // 000000000061FE1C,地址不变return 0;
}
形参与函数内的其他局部函数一样,在进入函数时被创建,退出函数时被销毁
把实际的值复制给函数的形参,不共享内存
值传递只传值 地址永远不变
#include
int main()
{int a=20;int b=10;int c=a;c+=1;printf("a %d\n",a); // 20printf("c %d\n",c); // 21printf("a %d\n",a); // 20return 0;
}
进阶
想当于复制,内存地址不一样
且修改B不会影响A
#include
int main()
{int a=20;int b=10;int c=a;printf("%p\n",&a); // 000000000061FE18printf("%p\n",&c); // 000000000061FE14c+=1;printf("a %p\n",&a); // 000000000061FE18printf("c %p\n",&c); // 000000000061FE14return 0;
}
形参为指向 实参地址 的指针,当对 形参的指向操作时,就相当于对 实参 本身进行的操作
#include
#include // 要是返回一个指针,则要用dataType* 的方式进行定义
char *strlong(char* s1,char* s2){if (strlen(s1)>=strlen(s2)){return s1;}else{return s2; }
}int main(){char s1[30]="hello";char s2[30]="world";char *s3;s3="ex";s3=strlong(s1,s2);printf("%s\n",s3);return 0;
}
python的传值方式是按照c++中传指针的方式传值的,即不是引用也不是值。如果对象是可变的,那么操作是在传入对象上操作的,如果是不可变的,那么操作后相当于这个标识符指向了另一个对象
(c++传指针本质上也是值传递,只不过传的是地址值,这时候由于是值传递地址值不会被修改,但是存放在地址里的实参的值是可修改的,这时候对应于python传入对象可变的话相当于就在原对象地址上修改这个对象。如果对象本身不可变,相当于传递的是指针常量,自然不能修改这个对象)
python的赋值
a=1
a=2
# 前后两次id(a)不同
引用传递是基于指针的
引用符号&相当于别名,并不是取地址,即共享一段内存(引用传递数值,会修改原始的数据的)
通过指针传递地址到函数,实现在函数内部操作函数外部的数据
数组、字符串、动态分配的内存,不能通过一个参数直接传递
将指针作为形参,地址作为实参进行传递
返回类型(return_type):一个函数可以返回一个值;不返回值得时候
return_type
是void
参数(parameter_list):形参列表
return_type function_name(parmeter_list)
{...;
}
函数声明会告诉 编译器 函数名称 及 如何调用函数
函数的实际主体可以单独定义
形参的名称并不重要,只有参数的类型是必须的
// 方法1
int max(int num1,int num2)
{...
}// 方法2
int max(int num1,int num2); //注意是分号// 方法3
int max(int,int)
在A文件中声明和定义,在B文件中调用,则需要在调用函数的文件B的顶部声明函数
#include
#include // version 1 这里a变成了指针
void func(int a[],int n)
{for (int i=0;iprintf("%d\n",a[i]);}
}// version 2 直接使用指针
void func2(int *a,int n)
{for (int i=0;iprintf("%d\n",a[i]);}
}int main()
{int a[10]={1,2,3};func(a,sizeof(a)/sizeof(int));func2(a,sizeof(a)/sizeof(int));
}
二维数组
// version 1
void func(int a[][3],int m,int n)
{for (int i=0;ifor (int j=0;jprintf("%d,%d,%d\n",a[i][j],*(a[i]+j),*(*(a+i)+j));}}
}// version 2
void func(int (*a)[3],int m,int n)
{for (int i=0;ifor (int j=0;jprintf("%d,%d,%d\n",a[i][j],*(a[i]+j),*(*(a+i)+j));}}
}int main()
{int a[2][3]={1,2,3,4,5,6};func(a,sizeof(a)/sizeof(int),sizeof(a[0])/sizeof(int));// func2(a,sizeof(a)/sizeof(int));
}
// 值传递
// strcut1=struct2 可以进行赋值,但是相当于副本,二者没有任何关系
void func(struct struct_name struct_param)
{/*code*/
}
struct struct_name struct_param;
func(strct_param); // 只是传递的副本,并不会修改外部参数,相当于值传递//地址传递
void func(struct struct_name* struct_param)
{/*code*/
}
struct struct_name struct_param;
func(&strct_param); // 会修改外部参数,相当于地址传递
#include #define MaxSize 10
typedef struct
{int data[MaxSize];int length;
}SqList;void InitList(SqList *L)
{for (int i=0;iL->data[i]=0;}L->length=0;
}int main()
{SqList L; //等价于Struct LInitList(&L);for (int i=0;iprintf("%d\t",L.data[i]);}printf("\n%d\n",L.length);return 0;
}
将指针作为函数的返回值,指针就是一个地址
见引用传递
注意局部变量作为指针函数的返回值情况函数运行结束后会销毁在他内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们会在后续使用过程中可能引发运行时错误
// 下面的例子,有的编译器直接报错,提示 返回局部变量的指针
int *func()
{int n=100;return &n;
}int main()
{int *p=func(),n;n=*p;printf("%d\n",n);return 0;
}
itoa()
#include
int a=10;
char s[10]={0};
itoa(a,s);
printf("%s\n",s)char a='a';
char buffer[10];
itoa(a,buffer,2); // 2表示转换基数
sprintf
// 整型转字符串
int a=120;
char str[20];
memset(str,0,sizeof(str));
sprintf(str,"%d",a);
printf("%s\n",str);
printf("%d\n",sizeof(str));