输出结果:会输出无数个‘=’
解析:unsigned int 的取值范围是0~4294967295(2^32-1)
当i减到0的时候,再一次减1就会变成4294967295,这样的话就一直满足i>=0的条件,所以会输出无数个‘=’。
知识点一:
unsigned int:无符号整型,表示从0开始到2^32-1的所有整数,
unsigned后面的int可以省略
递减运算符–(顺便也把递增运算符++了解一下叭)
递增递减运算符
“++”和“–”是两个很特殊的运算符,它们是单目运算符,这个算子还必须是变量。这两个运算符分别叫做递增和递减运算符他们的作用就是给这个变量+或者-1。
例如:
count++:
count +=1
count=count+1
前缀后缀
●++和–可以放在变量的前面,叫做前缀形式,也可以放在变量的后面,叫做后缀形式。·a++的值是a加I以前的值,而++a的值是加了I以后的值,无论哪个,a自己的值都加了I了。
解析:
(1) 使用了一个中间变量 ,先把a的值赋给中间变量,再把b的值赋给a,再把中间变量的值赋给b;
(2) 通过数学运算 将两个变量的值进行交换;
(3) 按位异或(^) :两者相同为0,不同为1;用异或运算讲a与b相应位若相同记为0,不同记1,其值给a,再将b与a进行异或运算实现b到a的转变,再用a与b进行异或运算实现a到b的转变.
输出结果:1,1(多次执行b的值会一直是1,a的值会一直增加)
解析:使用static修饰符定义静态局部变量,它的生命周期是整个应用程序的运行时间,只会被初始化一次,所以第一次执行的时候a的值是1,多次执行a的值就会递增。
知识点二:
♞static关键字的功能
①先来介绍它的第一条也是最重要的一条:隐藏。
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。
②static的第二个作用是保持变量内容的持久。 存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。
③static的第三个作用是默认初始化为0 。其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。
☞学以致用,做道题叭
输出结果:5 5
BUT!!多次执行num的值会按照5的倍数递增5,10,15
拓展小知识(芝士 就是力量)
★static全局变量和普通全局变量区别:
static全局变量和普通全局变量存储方式都为静态存储方式,区别在于各自的作用域,普通全局变量的作用域是整个源程序,,当一个源程序由多个源文件组成时,普通全局变量在各个源文件中都有效,而静态全局变量则限制了作用域,只在定义该变量的源文件中有效.
★static局部变量和普通局部变量区别:
static局部变量和普通局部变量的存储方式即生存期不同,static局部变量具有全局的生存期, 只初始化一次, 离开函数后仍然存在, 具有函数内的局部作用域,是特殊的全局变量.
★static函数和普通函数区别:
static函数与普通函数作用域不同,仅在本文件.只在当前源文件中使用的函数应该说明为内部函数即static修饰的函数,内部函数应该在当前源文件中说明和定义.对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件.
输出结果: Xiyou Linux Group2019
解析:
函数嵌套,先打印了一个空字符,之后打印Xiyou Linux Group2,0通过%d被打印出来,19作为返回值被最后一次printf函数打印出来
知识点:
printf的返回值:
printf()函数也有一个返回值,它返回打印字符的个数.
大部分C函数都有一个返回值,这是函数计算并返回给主调程序的值.可以把返回值赋给变量,也可以用于计算,还可以作为参数传递.
输出结果:没有给a赋值,运行程序时编译器会报错,如果忽略,则ch输出-1
解析and知识点:
char类型的取值范围为-128~127
255是一个整数,在计算机中存储数据采用补码的形式,而正数原码补码相同,
例如 :
原码 1111 1111
反码 1111 1111
补码 1111 1111
用char来看待这个二进制数字,由于符号位为1,则为负数,负数由补码求原码
补码 1111 1111
原码 1000 0001
所以呢,1111 1111用int来看是255
用char来看是-1.
输出结果:
x=-1,y=4,t=-1
x=0,y=5,t=1
知识点:
递增递减运算符(第一题中有所以在这里就不说啦)
按位运算
看完清清楚楚的图,现在你是明明白白的叭ฅ˙Ⱉ˙ฅ
☞练一道题就更明白啦
小小解析:十进制的7对应二进制的111
所以呢这段代码的功能就是把十进制转化成二进制
下面是逻辑运算啦
逻辑运算的结果
在编程中,我们一般将零值称为“假”,将非零值称为“真”。逻辑运算的结果也只有“真”和“假”,“真”对应的值为 1,“假”对应的值为 0。
①与运算(&&)参与运算的两个表达式都为真时,结果才为真,否则为假。
例如:
5&&0
5为真,0为假,相与的结果为假,也就是 0。(5>0) && (4>2)
5>0 的结果是1,为真,4>2结果是1,也为真,所以相与的结果为真,也就是1。
②或运算(||)参与运算的两个表达式只要有一个为真,结果就为真;两个表达式都为假时结果才为假。
例如:
10 || 0
10为真,0为假,相或的结果为真,也就是 1。(5>0) || (5>8)
5>0 的结果是1,为真,5>8 的结果是0,为假,所以相或的结果为真,也就是1。
③非运算(!)参与运算的表达式为真时,结果为假;参与运算的表达式为假时,结果为真。
例如:!0
0 为假,非运算的结果为真,也就是 1。
!(5>0)
5>0 的结果是1,为真,非运算的结果为假,也就是 0。
输出结果:3
解析:
你是不是认为结果是4但是,不是这样啦,应该是1+1*1+1=3因为这里没有(),所以先算乘法,如果是4应该这样写:
#define X(a+b)
知识点:
宏定义一般形式:
#define 标识符 字符串
其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。
“标识符”为所定义的宏名。
“字符串”可以是常数、表达式、格式串等。
例如:#define M (a+b)它的作用是指定标识符M来代替表达式(a+b)。
在编写源程序时,所有的(a+b)都可由M代替,而对源程序作编译时,将先由预处理程序进行宏代换,即用(a+b)表达式去置换所有的宏名M,然后再进行编译。
注意:定义M来替代表达式(a+b),若 s= M * M 在预处理时经宏展开后该语句变为: S=(a+b)(a+b)注意的是,在宏定义中表达式(a+b)两边的括号不能少 ,否则会发生错误。
☞啥也不多说,练题
输出结果:11
2+23+3=11
第一行:定义了一个int类型的变量val并初始化为2018;
第二行:声明了一个int类型的指针变量pi并初始化为2019;
第三行:将val变量的地址赋给pi;(&为取地址符)第四行:将pi指向的空间所存储的数据改为0.
第二行代码解析:为20个char类型的值请求内存空间,并设置p指向该位置.
第三行代码解析:声明指针变量q,指向p所指向的空间(p和q指向了同一个地址.)
输出结果解析:输入Xiyou空格后改变了*p的值,再输入Linux 回车后改变了*q的值(实际改变的是同一个地址的数据),之后输入的Linux覆盖了之前输入的Xiyou,所以输出结果是:Linux Linux
解析:
每次执行输出的结果不一致,a分配的内存是动态的,所以a的地址一直变.
a表示数组的首地址
&a表示数组首元素的地址
a+1表示数组首地址加上一个元素 所占的地址大小,
int为4个字节,所以加4(1*4)
&a+1表示加上整个数组的大小,
这里数组尺寸是4,所以+1代表的是地址加上16(4x4).
#include<stdio.h>//头文件
int main()//主函数,程序的入口
{
int i,f1,f2,f3,row; //定义变量
f1=1,f2=1; //变量初始化
printf("输入需要输出的行数:");//提示语句
scanf("%d",&row); //键盘输入行数
printf("%d\n%d\n",f1,f2); //先输出第一行和第二行
for(i=1;i<row-1;i++) ///循环控制后row-2行
{
f3=f2+f1; //第3行的值是前面两行之和
printf("%d\n",f3);
f1=f2; //变量赋值
f2=f3;
}
}
递归
#include<stdio.h>
int f(int n)
{
if(n==1||n==2)
return 1;
else
return f(n-1)+f(n-2);
}
int main()
{
int i;
scanf("%d",&i);
printf("%d",f(i));
return 0;
}
冒泡排序
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
算法描述
①比较相邻的元素。如果第一个比第二个大,就交换它们两个;
②对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
③针对所有的元素重复以上的步骤,除了最后一个;
④重复步骤1~3,直到排序完成。
稳定性
在相邻元素相等时,它们并不会交换位置,所以,冒泡排序是稳定排序。适用场景冒泡排序思路简单,代码也简单,特别适合小数据的排序。但是,由于算法复杂度较高,在数据量大的时候不适合使用。
代码优化
在数据完全有序的时候展现出最优时间复杂度,为O(n)。其他情况下,几乎总是O( n2 )。因此,算法在数据基本有序的情况下,性能最好。要使算法在最佳情况下有O(n)复杂度,需要做一些改进,增加一个flag的标志,当前一轮没有进行交换时,说明数组已经有序,没有必要再进行下一轮的循环了,直接退出。
#include<stdio.h>
#include<stdbool.h>
int main()
{
int a[10];
int n;
int temp;
bool flag=true;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(int i=0;i<n-1&&flag;i++)
{
for(int j=0;j<n-1-i;j++)
{
flag=false;
if(a[j]>a[j+1])
{
flag=true;
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i=0;i<n;i++)
{
printf("%d ",a[i]);
}
return 0;
}
下面我们来了解了解选择排序
选择排序
选择排序是一种简单直观的排序算法,它也是一种交换排序算法,和冒泡排序有一定的相似度,可以认为选择排序是冒泡排序的一种改进。
算法描述
①在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
②从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
③重复第二步,直到所有元素均排序完毕。
稳定性
用数组实现的选择排序是不稳定的,用链表实现的选择排序是稳定的。不过,一般提到排序算法时,大家往往会默认是数组实现,所以选择排序是不稳定的。
适用场景
选择排序实现也比较简单,并且由于在各种情况下复杂度波动小,因此一般是优于冒泡排序的。在所有的完全交换排序中,选择排序也是比较不错的一种算法。但是,由于固有的O(n2)复杂度,选择排序在海量数据面前显得力不从心。因此,它适用于简单数据排序。
#include<stdio.h>//头文件
int main()//主函数
{
int i,j,min,temp,array[11];//定义整型变量和数组
printf("输入数据:\n");//提示语句
for(i=1;i<=10;i++)//依次键盘录入10个数据
{
printf("array[%d]=",i-1);//数组下标从0开始
scanf("%d",&array[i]);
}
printf("\n");//换行
printf("原样输出:\n");//提示语句
for(i=1;i<=10;i++)//将键盘录入的10个数原样输出
{
printf("%5d",array[i]);
}
printf("\n");//换行
for(i=1;i<=9;i++)
{
min=i;//把第一个数作为最小的
for(j=i+1;j<=10;j++)
{
if(array[min]>array[j])//判断大小,小的为min
{
min=j;
}
}
temp=array[i]; //大小交换
array[i]=array[min];
array[min]=temp;
}
printf("排序输出:\n");//提示语句
for(i=1;i<=10;i++)//输出排序后的10个数
{
printf("%5d",array[i]);
}
printf("\n");//换行
return 0;//主函数返回值为0
}
字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。
小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;
大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处.
#include<stdio.h>
int main()
{
short int x=0x1122;
char x0,x1;
x0=((char*)&x)[0];
x1=((char*)&x)[1];
printf("%#x",x0);
return 0;
}
如果输出0x22则为小端
输出0x11则为大端
验证出我的机器是小端字节顺序
-al 指各项说明,查看设备是否具有读写权限.
第一列指文件类型及权限;
第二列指链接占用的节点;
第三列指文件所有者;
第四列指文件所有者的用户组;
第五列指文件大小;
第六列指文件的创建时间或者最近修改时间;
第七列是文件名称.