文章目录
- 数据与程序结构
- C语言的编程机制
- #include <>和#include ""的区别
- 形式参数和实际参数
- 值传递
- 地址传递
- 素数
文章内容摘自或加工于C技能树一些大佬的博文
数据与程序结构
阅读完C的编程机制和函数的声明和定义后的一些启发。——预处理
C语言的编程机制
- 预处理:#include<stdio.hj>以及宏定义相当于调用函数的声明(个人理解),预处理阶段把源程序(.c)中这些头文件宏定义替换为他们真正指向的函数。
- 编译:把预处理之后的文件(.i)转换成汇编代码(.s),也就是符号语言
- 汇编:把汇编代码(.s)转换成机器码(.o),也就是二进制文件
- 链接:把目标文件(.o)和相关的库文件(.so)链接在一起生成可执行文件(.exe)
#include <>和#include ""的区别
二者的区别在于:当被include的文件路径不是绝对路径的时候,有不同的搜索顺序。
1> 对于使用双引号""来include文件,搜索的时候按以下顺序:
先在这条include指令的父文件所在文件夹内搜索,所谓的父文件,就是这条include指令所在的文件
如果上一步找不到,则在父文件的父文件所在文件夹内搜索;
如果上一步找不到,则在编译器设置的include路径内搜索;
如果上一步找不到,则在系统的INCLUDE环境变量内搜索
2> 对于使用尖括号<>来include文件,搜索的时候按以下顺序:
在编译器设置的include路径内搜索;
如果上一步找不到,则在系统的INCLUDE环境变量内搜索
形式参数和实际参数
形式参数
形参出现在被调函数当中,在整个函数体内都可以使用。形参在定义时编译系统并不分配存储空间,只有在调用该函数时才分配内存单元。调用结束内存单元被释放,故形参只有在函数调用时有效,调用结束时不能再使用。
实际参数
实参出现在主调函数当中,当函数调用时,主调函数把实参的值传送给被调函数的形参,从而实现函数间的数据传递。传递方式有两种:值传递和地址传递方式。
值传递
值传递是形参与实参之间进行的是数据交换,而形参的周期从调用开始生效,到调用完就被释放死掉了,所以形参不具有改变实参的功能。当实参是常量、变量,数组元素(下标变量)和表达式,这种值传递时,形参部分可以定义如下:
//形参实现部分
int swap(int a,int b)
{
int temp;
temp = a;
a = b;
b = temp;
return 0;
}
//形参在主函数中调用部分
swap(int a,int b);
主函树、实参定义部分
//定义实参为常量时,有以下两种方式:
const float PI = 3.14; //用此举例子
#define PI 3.14
//主函数部分
int main(int argc, char **argv){
//实参为常量,方式二
const int A = 3;
const int B = 4;
swap(A,B);
printf("A = %d,B = %d",A,B);
}
//定义实参为变量时
//主函数部分
int main(int argc, char **argv){
int a = 1;
int b = 2;
swap(a,b);
}
//定义实参为表达式时
//主函数部分
int main(int argc, char **argv){
int a,b,c,d,x,y;
a=1;b=2;c=3;d=4;
x = a+b;
y = c+d;
swap(x,y);
}
//定义实参为函数元素时
//主函数部分
int main(int argc, char **argv){
int a[]={1};
int b[]={3};
swap(a[0],b[0]);
}
注意:(数组元素,比如a[0],又称为下标变量,它具有普通变量的一切性质,也归为变量,是值传递)
地址传递
由于是参数组和形参数组都指向同一段内存单元,故它们操作的是同一批数据,所以形参的改变就是改变了实参中的数据。数组名,数组指针这种地址传递的方式时,此时形参部分可以定义如下:
//形参实现部分
int swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
return 0;
}
//形参在主函数中调用部分
swap(int a,int b);
主函树、实参定义部分
// 实参为数组指针
//主函数
int main (void){
int arr[] = {1,2};
int *a = &arr[0];
int *b = &arr[1];
swap(a,b);
}
// 实参为数组名
//主函数
int main (void){
int a[] = {1,2};
int b[] = {3,4};
swap(a,b);
}
注意:
(1)数组名是一个地址,是数组的首地址,因此用数组名作为函数的参数进行数据传递时,执行的是地址传递方式。
(2)数组指针,即数组元素的地址。
素数
/*
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
*/
// 定义一个判断素数的函数,参数为n
int prime(int n){
int is_prime = 1, i;
// 如果n小于0,返回-1,表示不符合条件
if(n < 0){ return -1; }
// 循环遍历2到n-1之间的所有数
for(i=2; i<n; i++){
// 如果n能被i整除,说明n不是素数,将is_prime置为0,跳出循环
if(n % i == 0){
is_prime = 0;
break;
}
}
// 返回is_prime的值,如果为1表示是素数,为0表示不是素数
return is_prime;
}
注意:如果将上面的代码中素数函数改成无返回值的,即 “int prime(int n){}” 修改为 “void prime(int n){} ”,则{}里面出现 “return -1;” 虽然可以运行,但是无意义的,可以修改为“return 1;”或者 “return ;”