初学C语言02(4_06)
(欢迎各位在评论区指正不足)
1.字符串+转义字符:
有双引号引起来的一串字符称为字符串,例如:
int main()
{
"hello world";
"abcdefg";
return 0;
}
字符串中结束的标志是\0,为计算字符串长度的结束标志,但是其本身不算做是字符串内容,可以通过定义两个字符数组来理解:
#include<stdio.h>
int main()
{
char arr1[] = "abc";//双引号引起来的叫一串字符
char arr2[] = {'a','b','c'};//大括号里面单引号引起来的叫单个字符
printf("%s\n",arr1);
printf("%s\n",arr2);//我们将上述两个字符数组进行打印,看看有什么区别
return 0;
} //当然我们也可以打开监视窗口按下f10进行监视
如上图,arr1打印符合预期,但是arr2打印完abc之后出现一排乱码,其原因就在于:它是单个字符放入,最后漏放了一个’\0’,这就导致电脑往后面继续打印直到在后面的一个内存空间之中碰到了一个随机的’\0’方才停止。
如上图监视窗口可知道:每个数组都是从0开始的,第一个数组有第三项’\0’
但是第二个数组没有第三项,由此可见,这再一次证明了,’\0’确实是字符串结束的标志
转义字符,顾名思义,就是转变意思
例,当我们想要在屏幕上打印一个文件的目录时:
#include <stdio.h>
int main()
{
printf("c:\code\test.c\n");
return 0;
}
出现的结果却是这样 的:
此处出现的歧义就是因为转义字符
如果想要打印内容符合预期:
printf("c:\\test\\test.c");\\方法就是在原来的斜杠之前再加上一个斜杠,把原来的意思转变掉,同样地,下面还有
printf("%s\n,"\"");\\此处我想单独打印一个",但是又不想被电脑解读成前面两个双引号在一起,于是就加一个\把它给转义掉
printf("%s\n,"\'")\\此处想单独打印一个',方法同上
特别注意,问你测量字符串长度的结果时,最后一个\ddd,如果三个数字中没有8,则算作一个
如果有8,那么挨个算
2.选择语句:详解
3.循环语句:详解
4.函数:
例子:
函数的传递方式如上图所示
注意事项:
- 函数上面最前面(add)也要定义变量的类型
- 最后接受函数的值的变量也要定义其类型(即sum前面)
5.操作符:
注意:这里要想算出来的数是小数,那就要用小数的形式来写
#include <stdio.h>
int main()
{
float a = 9.0/2;
printf("%f",a);
}//被除数和除数中必须要有一个是以小数形式写的,并且前面必须用float来存放
//这样最后才能保证a是4.5
上面两个分别为左移操作符和右移操作符
他们移动的是二进制位,例如:
#include <stdio.h>
int main()
{
int a = 2;
int b = a << 1;//此处表示a的二进制位向左移一位
return 0;
}
因为a的值为2且存放在整型之中,一个int的空间为4个字节,每个字节下面有分8个比特位,所以可得移位的解:
左移一位后空出来的一个比特位默认补上0,因此上面代码块中,b的值为 :4
以上均为符合操作符:a=a+1简记为a+=1
-
单目操作符:
- ~ 此为按二进制位取反
计算机中的数据是按照补码的形式储存在计算机中的
负数的补码求法:第一个符号位不变,剩下的数字逐位取反,,是为反码
之后反码加一,即为该负数的补码
正数的原反补相同(没有为什么,只是因为规定即如此)
& 此为取地址符,可以取出相应数据的地址
size of 测量操作数的类型长度(以字节为单位)
- ++ 加加分为前置加加和后置加加。前置加加先让原来的数自增,再赋给对应的变量
后置加加先把原来的值赋给变量,再将自身的值自增
- – 减减分为前置减减和后置减减。前置减减先让原来的数自减,再赋值给对应变量
后置减减先把原来的值赋给变量,在将自身的值自减
注意:加加和减减每次变化只有1
int b = ++a; int b = a++;//前置加加与后置加加 int d = --c; int d = c--;//前置减减与后置减减
- *此为间接访问操作符(解引用操作符)
#include <stdio.h> int main() { int a = 10; int* pa = &a;//其中pa即为一个指针,里面存放着a的地址,int表明了其指向数字的类型 *pa = 20 ;//到这里a的值变为了20,*就是解引用操作,*pa通过自己里面存的a的地址从而 //找到a,然后将20这个值赋给a return 0; }
-
关系操作符:>大于,>=大于等于,<小于,<=小于等于,!=不等于,==相等
-
逻辑操作符: &&逻辑与(有一个假全为假),||逻辑或(有一个真全为真)
-
条件操作符:exp1 ? exp2 :exp3
解释:此操作符执行时先判断表达式1(exp1)是否成立,若成立结果为表达式2(exp2)的结果
若exp1不成立则为exp3的结果
例如:
#include <stdio.h>
int main()
{
int a = 0;
int b = 3;
int max = 0;
max = a>b?a:b;
printf("%d\n",max);
return 0;
}
6.逗号表达式:
( exp1,exp2,exp3,exp4…exp4)
#include <stdio.h>
int main()
{
int a = 0;
int b = 4;
int c = 7;
int d = (a = b+2,b = c+a ,c = a+b);//三个表达式从左到右依次运算,最终d的结果永远 //是最后一个表达式算出来的结果
return 0;
}
7.下标引用、函数调用和结构成员:
[ ]下标引用操作符
int arr[] = {0,1,2,3,4,5,6};
printf("arr[5]")//此处实现了下标的引用
()函数调用操作符
printf("hehe\n");//此处表示只传一个参数
printf("%d\n",100);//此处表示传了两个参数,当然了也可以一个参数都不传
8.常见关键字:
- 关键字由C语言本身具备,不可以自行定义
- 变量的命名不能与关键字冲突
auto 这个在每一个变量类型的前面,正常都是省略的,无须写出来
auto int a = 0;//最前面的auto正常都是略去
extern 这个关键字用于声明外部符号,前面已经有过交带
register 此处表示优先把数据存到寄存器之中
typedef 用来定义给类型重命名,主要起到了一个简化的作用
譬如:typedef unsigned int u_int ,此处就把原本冗长的unsigned int 变成了u_int
9.static 此关键字可以用来修饰局部变量,全局变量和函数,修饰后两者可以改变其链接属性:
例如:
如上面两个图,图1中的a每出一次函数的作用域即销毁一次,故而每次自增前的值都为1,最后打出来的也都是清一色的2,共打了十个二
图2因为函数里的a被static修饰过了,所以出了函数里的作用域不销毁,每次再进函数的时候保留上一次的值,故而最终的打印结局为:2至12
static修饰过的全局变量也没有办法作用于别的文件,主要是因为全局变量被修饰之后就被储存在了静态区,即将全局变量的外部链接属性改成了内部链接属性,无法从外部调用
同样的,函数也是如此,在文件1中写好的函数,到文件2中再去调用也没有办法调,理由同上
static int add(int x,int y)
{
return x+y;
}//此处为一个.cpp文件
extern int add(int,int);//此处为第二个.cpp文件中对上一个文件的调用,但其实是无效操作
//原因就在于这个函数的外部链接属性被改为了内部链接属性
static int a = 0;//假设此处为第一个cpp文件
extern int a; //假设此处为第二个cpp文件
{
prntf("%d\n",a);//同样的,此处也是static改变了其外部链接属性为内部链接 //属性,所以,上图中的第一行其实为无效操作,无法将变量引用 //过来
return 0;
}
上图即为static修饰局部变量的作用原理,static通过改变其存储方式,将原本放在栈区的局部变量放到静态区,使局部变量出了其作用域不销毁,仍然能够保持原来的值(例子见上述两张插图)
10.#define定义的常量与宏:
define是一个预处理指令
- define 定义常量,例子如下:
#include <stdio.h>
#define max 100;
int main()
{
printf("%d",max);
return 0;
}
- define 定义宏,例子如下:
#define add(x,y) x+y
int main ()
{
printf("%d\n",add(2,3));//此处的参数传到对应的变量之中,得到结果为5
printf("%d\n",4*add(2,3));//此处结果为11,并非预期的20,原因是他的运算 //逻辑为4先和2乘,再去加3
//若想要式子符合预期那么则需要把原来的定义的 //宏里的变量x y看是表达式写成((x)+(y))
return 0;
}
#define add(x,y) ((x)+(y))//此处即为正确的书写方法
- 指针:
首先要从计算机的内存的概念说起:
因此当我们创建一个变量的时候,譬如创建一个整形变量int的时候,它开辟了四个字节
那么该变量的地址人为规定就是四个字节中第一个的地址,而如果我们创造一个指针(如:int * pa = &a)去储存它的地址存的也是第一个字节的地址,通过这第一个字节的地址从而找到下面的变量的地址
并且还有要注意的是指针所占空间的大小只能是4个字节或者8个字节,主要是因为指针之中存储的是变量地址,上图已经说过,变量地址是由32个或64个二进制数来表示的,其中每一位数字都占据一个bit,8 bit为1 byte,因此变量地址占据的的空间必须是固定的
11.结构体:
我们的日常生活之中有的对象具有复杂性,为了更好地描述事物,所以便有了结构体。譬如一个学生,我们要想描述好他,要有身高,体重,成绩,等等数值。
下面举个例子来详细了解
struct stu
{
char name[20];
int age;
double score;//此处,3 4 5行均为结构体的成员变量
};//注意这里的;不要漏掉
int main()
{
stru stu s = {"张三",20,85.5};//此处即为创建一个结构体变量s,并将该结构体s进行了初始化
printf("%s,%d,%lf",s.name,s.age,s.score);//此处使用了.操作符,用.来访问结构体的成员变量
//访问的方法:结构体变量.成员变量
int * ps = &s;
printf("%s,%d,%lf",(* ps).name,(* ps).age,(* ps).score);//此处的指针*ps指向着结构体变量s,其实就相当于s,故 //这样操作也是可以的
printf("%s,%d,%lf",ps->name,ps->age,ps->score);//但是现在我们假设一种情况,如果我们只知道指针变量ps
//但是却不知道结构体变量是什么,那么就可以用上面两种操作,通过指针直接访问
}