学习一门编程语言是一条艰辛与快乐共存的一条路,如今选择了这条路,就应该一直走下去,了解C语言的基础知识,要先对C语言有一个大概的认识,下面我介绍一下C语言的基础。
一、什么是C语言。
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。 二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8 日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。 C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。 二、C语言编程代码的基本格式。
#include int main(){printf("Hello\n");printf("Just do it!\n");return 0; }
打印结果:
有\n(这是换行操作符,下面会介绍)
无\n
2.1 #include :每一个C语言程序代码都含有的一个头文件,其中include 称为文件包含命令,其意义是把尖括号或引号””内指定的文件包含到本程序中,成为本程序的一部分。被包含的文件通常是由系统提供的,其扩展名为.h,而stdio为standard input output的缩写,意为“标准输入输出” ,在程序中为固定格式,输入上去就行。
2.2 int main():main函数是程序的入口 ,一个工程中main函数有且仅有一个,是C语言main函数的一种声明方式,在int main()下有一对{},在其中输入代码。
2.3 printf:表示要输出的结果,其结果放入(” “)中的双引号内,如果需要特别打印某一种字符类型,一般格式为(“需要打印的数据类型\n”,需要输出的变量)蓝色部分表示固定的格式。绿色部分表示需要打印相应内容时输入的不同的东西,\n表示换行,可有可无,只是打印出的结果格式不同不影响打印内容,具体需要打印的类型见后边。
2.4 return 0:返回值为0,先不做深入了解,记作固定的格式,打上去就行。
注:每一个语句后面需要打上一个英文输入下的分号 ;
三、数据类型
char 字符数据类型 short短整型 int整形 long 长整型 long long 更长的整形 float 单精度浮点数( 有效数字8位,表示范围:-3.40E+38~3.40E+38 ) double 双精度浮点数( 有效数字16位,表示范围:-1.79E+308~-1.79E+308 ) 注:每一种类型的空间大小不同 各种数据类型的空间大小:
#include int main(){printf("%d\n", sizeof(char));printf("%d\n", sizeof(short));printf("%d\n", sizeof(int));printf("%d\n", sizeof(long));printf("%d\n", sizeof(long long));printf("%d\n", sizeof(float));printf("%d\n", sizeof(double));printf("%d\n", sizeof(long double));return 0; }
代码中%d打印的是整型,sizeof()用于打印数据类型的大小。
打印结果:
其中数字大小表示各种数据类型的空间大小,单位为字节(byte)1GB=1024MB 1MB=1024KB 1KB=1024byte1字节=8位 其中位:是二进制数据中的一个位(bit)简写为b,音译为比特,是计算机存储数据的最小单位。
四、常量与变量
常量: 不变的值, C 语言中用 常量 的概念来表示,在生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)。 变量: 变的值, C 语言中用 变量 来表示(比如:年龄,体重,薪资)。 4.1 定义变量的方法
int age = 150;float weight = 45.5f;char ch = 'w';
选择需要定义变量的类型(int、char、float等),给变量相应的变量名字(自己灵活定义即可,最好方便自己记忆,比如需要对年龄赋值时,变量名用age),用 = 进行赋值,将值放在等号后面,并习惯性的打上分号。
4.2 变量的分类
全局变量:定义在int main()以外,对整个代码有效
局部变量:定义在某一个范围内用{ }括起来的区域,当出了该范围则无效,如果全局变量和局部变量一起存在,则局部变量优先。
#include int b = 2020;//全局变量int main(){int b = 2021;//局部变量int c = 2022;//局部变量printf("b = %d\n", b);return 0; }
打印结果:
4.3 变量的使用
我们以计算两个数字的和为例
#include int main(){int num1 = 0; int num2 = 0;int sum = 0;printf("输入两个操作数:>");scanf("%d %d", &num1, &num2);sum = num1 + num2;printf("sum = %d\n", sum);return 0; }
随机输入两个数字
代码中先定义需要输入的两个数字整型int num1=0;int num 2=0;其中赋一个初始值0,在定义一个变量来存放需要输出的值int sum=0;均放上初始值0;先输出一个提示语输入两个操作数:>用scanf(“%d %d”,&num1,&num2)来寻找变量num1和num2的地址,达到对变量随时赋值的目的,sum=num1+num2定义算法,即求两个数的和,并将结果用变量sum来承接,最后用printf来输出sum的值。
4.4 变量的作用域和生命周期 1.作用域: 是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效,可用 的,而限定这个名字的可用性的代码范围就是这个名字的作用域。 1. 局部变量的作用域是变量所在的局部范围。 2. 全局变量的作用域是整个工程。 2.生命周期: 变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段 1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。 2. 全局变量的生命周期是:整个程序的生命周期。
4.5 常量
C语言中的常量和变量的定义的形式有所差异
1.字面常量:即已知的值
2.const 修饰的常变量:对所赋值的变量有固定作用,后续不能改变
#include int main(){const int num = 4;printf("%d\n", num);int num = 8;//此处对num再赋值已经无效了printf("%d\n", num);return 0;}
其中const修饰的常变量,对赋值的sum有固定作用,后面再对num赋值则无效,虽然对num固定赋值了,但num的本质任然是变量,只是具有了常量的性质,验证如下:
#include int main(){const int n = 10;int arr[n] = { 0 };//数组[]中需要的是一个常量,虽然const修饰的n有常属性,但是他的本质是一个变量所以有错误return 0;}
所以没有输出结果:
3.#define 定义的标识符常量 :定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。例如:对MAX的赋值,在main函数外定义。
#include #define MAX 10int main(){int arr[MAX]={0};printf(" %d\n", MAX);return 0;}
4.枚举常量:需要一一列举出来,需要用到枚举关键字enum,放在枚举里边的叫枚举常量
#includeenum people{KID,MAN,WOMAN,};//其中KID,MAN,WOMAN,叫做枚举常量int main(){printf("%d\n", KID);printf("%d\n", MAN);printf("%d\n", WOMAN);return 0;}
五、字符串+转义字符+注释
5.1 字符串: 这种由双引号(Double Quote )引起来的一串字符称为字符串字面值( String Literal),或者简称字符串。比如第一个代码中的”Just do it!\n”
#include int main(){printf("Hello\n");printf("Just do it!\n");return 0; }
5.2 转义字符:转义字符是以“\”为开头的字符,后面跟一个或几个字符,其意思是将反斜杠“\”后面的字符转变成为另外的意思。
转义字符 | 释义 |
\0 | 结束标志 |
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\’ | 用于表示字符常量‘ |
\” | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。 如: \130 |
\xdd | dd表示2个十六进制数字。 如: \x30 |
1.先给大家介绍一下结束标志\0
#includeint main(){char arr1[] = "bit";char arr2[] = { 'b', 'i', 't' };char arr3[] = { 'b', 'i','t', '\0' };printf("%s\n", arr1);printf("%s\n", arr2);printf("%s\n", arr3);return 0;}
打印结果:
字符串放在数组里面时,末尾会默认输入一个 \0,也就是说在数组char arr1 [ ]={“bit”}中,其实放入的内容有‘b’,‘i’,‘t’,‘\0’,所以打印完bit后就结束了,然而在数组char arr2 [ ]={‘b’,‘i’,‘t’}这种单独的字符时,末尾是不会默认输入\0 的,所以在打印完bit以后并没有结束打印,而是打印了一些随机值。故出现一些“烫烫烫烫烫烫烫烫烫烫烫烫烫烫蘠it”,如果手动在末尾输入 \0 时,就手动给了一个结束标志,如数组char arr3 [ ]={‘b’,‘i’,‘t’,‘\0’},打印完bit遇到了\0,那么就结束打印。
2.转义字符 \? :在书写连续多个问号时使用,防止他们被解析成三字母词,三字母词存在于老一版的编译器中。
#includeint main(){printf("(are you ok\?\?)\n");// \?在书写连续多个问号时使用,防止他们被解析成三字母词return 0;}
打印结果:
3.转义字符 \’ 与 \” :只是单纯的为了输出单引号和双引号
#includeint main(){printf("\'");printf("\"");return 0;}
打印结果: 4.转义字符 \t :水平制表符,输出结果相当于一个按一次Tab健所拉开的距离
#includeint main(){printf("a\ta");return 0;}
输出结果:
其中两个字母a之间的间隔就是 \t 所拉开的一个Tab的距离 5.转义字符\ddd和\xdd: ddd 表示 1~3个八进制的数字。 如: \130 , dd 表示 2 个十六进制数字。 如: \x30 打印时输出的是对应表示的进制转化为十进制后,十进制对应ASCII码表对应的字符。
#includeint main(){printf("\101\n");printf("\x42");return 0;}
输出结果:
其中八进制\101转化为十进制表示的数是65,十六进制\x42转化为十进制表示的数是66
6.转义字符 \\: 用于表示一个反斜杠,防止它被解释为一个转义序列符,相当于将已经用 \ 转义的字符取消,如同双重否定是肯定的效果。而\\ 在代码中还有一个最常用的用法,用来解释代码意思,方便理解相应代码的功能,也方便他人阅读。
#includeint main(){printf("c:\\test\41\test.c"); return 0;}
输出结果:
其中\t叫作水平制表符相当于以一个tab健的一个空格位置,为防止\t被识别成转义字符,规定\\为反斜杠,防止他被解释为一个转义字符,与双重否定是肯定的意思差不多,八进制数\41转化为十进制是33,对应的ASCII码字符为!,其它字符没有转义字符,就直接打印出来
7.转义字符\a:警告字符,蜂鸣
#includeint main(){printf("\a");return 0;}
打印的时候会响一声“叮咚”
8.转义字符\b:退格符
#includeint main(){printf("abcdef\b\b\b\b");return 0;}
打印结果:
\b表示向后退格,退到相应位置时,相应的字符将无法打印,在退格的时候有叠加效果,如上代码中一共输入4个\b,相应向后退4格,在输入的abcdef中倒数第四位c将无法打印
9.转义字符\f:换页,将当前位置移到下一页的开头,在使用打印机时会直接换页,在编译器中表现不明显
10.转义字符\v:垂直制表符,也用于打印时
11.转义字符\r:回车,将当前位置移到本行的开头,并覆盖打印
#includeint main(){printf("abcdef\r");return 0;}
打印结果:
5.3注释:1. 代码中有不需要的代码可以直接删除,也可以注释掉
2. 代码中有些代码比较难懂,可以加一下注释文字 注释有两种风格: C语言风格的注释/*xxxxxx*/ 缺陷:不能嵌套注释 C++风格的注释//xxxxxxxx 可以注释一行也可以注释多行
以使用函数计算两个数的和为例:
#define _CRT_SECURE_NO_WARNINGS#includeint Add(int x, int y){return x + y;}/*C语言风格注释int Sub(int x, int y){return x-y;}*/int main(){int a = 0;int b = 0;//C++注释风格scanf("%d%d", &a, &b);//用scanf取a,b的地址,能够随机赋值计算printf("sum=%d\n", Add(a, b));//调用Add函数,完成加法return 0;}
打印结果:
六、选择语句:用if语句、switch case语句实现
如果好好学习,就能找到好工作 如果不学习,找不到好工作 这就是选择! 例如用if语句实现:
#define _CRT_SECURE_NO_WARNINGS#includeint main(){int num = 0;printf("学习编程\n");printf("你能够坚持吗?(0不能/1能)");//>:为提示符scanf("%d", &num);if (1==num)printf("好工作,高薪资");elseprintf("平淡的生活");return 0;}
七、循环语句:用while语句、for语句、do … while语句实现
有些事必须一直做,比如学习,应该日复一日
例如用while实现连续输入1-100的数字:
#includeint main()//代码功能:输出1-100的数字{int a = 1;//int b = 0;while (a < 101){printf(" %d", a );a += 1;}return 0;}
打印结果:
八、函数:是简化代码,代码复用。
8.1 库函数:当我们描述的基础功能,它们不是业务性的代码。我们在开发的过程中每个程序员都可能用的到,为了支持可移植性和提高程序的效率,所以C语言的基础库中提供了一系列类似的库函数,方便程序员进行软件开发。如:
1. 我们知道在我们学习C语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道结果,想 把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能:将信息按照一定的格 式打印到屏幕上(printf)。 2. 在编程的过程中我们会频繁的做一些字符串的拷贝工作(strcpy)。 3. 在编程是我们也计算,总是会计算n的k次方这样的运算(pow)。 如果想了解更多C语言的更多库函数可以去C++官网查看:C++官网(英文版):cppreference.comC++官网(中文版):cppreference.com也可去:cplusplus.com – The C++ Resources Network对库函数简单的分类: 1. IO函数 2.字符串操作函数 3.字符操作函数 4.内存操作函数 5.时间/日期函数 6.数学函数 7.其他库函数 注:但是库函数必须知道的一个秘密就是:使用库函数,必须包含 #include 对应的头文件。
8.2 自定义函数:如果库函数能干所有的事情,那就不需要程序员了, 所有更加重要的是自定义函数,自定义函数和库函数一样,有函数名,返回值类型和函数参数。 但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。
例如计算两个数的和:
#include int main(){int num1 = 0; int num2 = 0;int sum = 0;printf("输入两个操作数:>");scanf("%d %d", &num1, &num2);sum = num1 + num2;printf("sum = %d\n", sum);return 0; }
利用函数计算两个数的和:
#include int Add(int x, int y) {int z = x+y;return z; }int main(){int num1 = 0; int num2 = 0;int sum = 0;printf("输入两个操作数:>");scanf("%d %d", &num1, &num2);sum = Add(num1, num2);printf("sum = %d\n", sum); return 0;}
直接调用自己定义的函数int Add(int x, int y),就不需要重复的去敲代码,需要求两个数的和时直接调用函数就行了。
九、数组
9.1 定义:一组相同类型元素的集合
例:要存储1-10的数字,怎么存储?
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
9.2 数组的下标:C语言规定,数组的每个元素都有一个下标,下标是从0开始的。 数组可以通过下标来访问的。
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//如果数组10个元素,下标的范围是0-9
数组中各值对应的下标:
打印数组里面的数值:
#include int main(){ int i = 0; int arr[10] = {1,2,3,4,5,6,7,8,9,10}; for(i=0; i<10; i++) { printf("%d ", arr[i]); } printf("\n"); return 0; }
打印结果:
十、操作符:算术操作符、移位操作符、位操作符、赋值操作符
10.1 算术操作符:+-*(乘号)/(除号)%(取余)
1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
#define _CRT_SECURE_NO_WARNINGS#includeint main(){int a = 0;int b = 1;//对b赋的初始值不能为0,因为在后面要作为除数int c = (-8 + 22) * a - 10 + b / 2;int d = a % b;scanf("%d%d", &a, &b);printf("计算结果=%d\n", c);printf("取余=%d\n", d);return 0;}
打印结果:
10.2 移位操作符:<>右移操作符
1.移位操作符的操作数只能是整数
2.针对的是十进制转化为二进制后,对二进制的数值进行移位,
3.左移操作符,左边舍去右边补零
4.对于移位运算符,不要移动负数位,这个是标准未定义的
int main(){int a = 1;//int型有4个字节32个比特位转化为二进制00000000000000000000000000000001转化为十进制就为1int b=a << 2; //00000000000000000000000000000100转化为十进制就为4int b=a<<-1;//错误的移位printf("%d", b);return 0;}
打印结果:
移位操作符是针对二进制数进行移位,例如上述代码中int类型4个字节=4×8=32位,将对应的整数先转化为32位的二进制数,在对二进制数进行移位,移位遵循——左移操作符时,左边舍去右边补零;右移操作符时,右边舍去左边补零。最后再将移位后的二进制数转化为十进制数打印出来。
10.3 位操作符:&按位与|按位或 ^按位异或(均是对二进制进行)
#includeint main(){int a = 1;//0001int b = 2;//0010printf("%d\n", a & b);//0000printf("%d\n", a | b);//0011printf("%d\n", a ^ b);//0011 相同为0不同为1return 0;}
打印结果:
10.4 赋值操作符:=+= -= *= /= &= ^= |=>>=<<=
赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。 10.5 单目操作符:
操作符 | 作用 |
! | 逻辑反操作 |
– | 负值 |
+ | 正值 |
& | 取地址 |
sizeof | 操作数类型长度(以字节为单位) |
~ | 对一个数的二进制按位取反 |
— | 前置、后置— |
++ | 前置、后置++ |
* | 间接访问操作费(解引用操作法) |
(类型) | 强制类型转换 |
前五个操作符在前面已经介绍了,我向大家介绍后面五种就行
1.对一个数的二进制按位取反~:~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0,例:十六进制9对应:0x00000009 当取反时~9对应:0xfffffff6
#includemain(){int a = 0;printf("%x", ~a);}
打印结果:
2.前置、后置++:前置++作用是先进行运算再赋值,而后置++为先先复制后运算
前置++:
#include main(){int i = 2;int a=++i;int b = i;printf("a=%d\n", a);printf("b=%d\n", b);}
打印结果:
代码中我们先给 i 一个初始值2,用b来反应 i 最终的值。前置++是先对2进行+1运算,然后将加上1后的值3赋给变量a,故a的值为3,经过运算和赋值后 i 的值变为3,故将i变化后的值3赋给b,故b的值为3
后置++:
#include main(){int i = 2;int a = i++;int b = i;printf("a=%d\n", a);printf("b=%d\n", b);}
打印结果:
代码中我们先给 i 一个初始值2,用b来反映i 最终的值。后置++是先 i 的值2先赋给a,然后对 i 加1,则a的值为2,经过赋值和运算后 i 的值变为3,故将 i 变化后的值3赋给b,故b的值为3。
3.前置、后置–:
前置–:
#include main(){int i = 2;int a = --i;int b = i;printf("a=%d\n", a);printf("b=%d\n", b);}
打印结果:
代码中我们先给 i 一个初始值2,用b来反映i 最终的值。前置–是先对2进行-1运算,然后将减去1后的值1赋给变量a,故a的值为1,经过运算和赋值后 i 的值变为1,故将 i 变化后的值1赋给b,故b的值为1
后置–:
#include main(){int i = 2;int a = i--;int b = i;printf("a=%d\n", a);printf("b=%d\n", b);}
打印结果:
代码中我们先给 i 一个初始值2,用b来反映i 最终的值。后置–是先 i 的值2先赋给a,然后对 i 减1,则a的值为2,经过赋值和运算后 i 的值变为1,故将 i 变化后的值1赋给b,故b的值为1。
4.间接访问操作费(解引用操作法) *:该操作符常用于指针
#includeint main(){int a = 10;int* p= &a;*p =20;printf("%d\n", a);return 0;}
打印结果:
想要了解此代码需要先了解指针的概念,可先往下翻,初步了解指针。代码中*p=20;其中的*就是解引用操作符,意思是通过p中存放的地址,找到p所指向的对象,而*p就是p所指向的对象,其代表的就是变量a。
5.强制类型转换(类型):
#includeint main(){double a = 3.14;printf("%d\n", (int)a);return 0;}
打印结果:
原本定义的变量是double型,在(类型)的强制转换下,将变量a转换为int类型,使用该操作符时,将需呀转化的类型放入括号内,将需要转化的变量紧放其后切只对一个变量有效,如果在()后有两个变量,则只对紧跟的第一个变量有效该转换只能在该语句生效,并且在其他地方,变量a仍然是double类型。
10.6 关系操作符:
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
!= | 用来测试“不相等” |
== | 用来测试“相等” |
10.7 逻辑操作符:
&& | 逻辑与 |
|| | 逻辑或 |
10.8 条件操作符:exp1 ? exp2 : exp3 10.9 逗号表达式:exp1, exp2, exp3,……expN 10.10.下标引用、函数调用和结构成员:[] () . ->
十一、常见关键字:C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。
autobreak casecharconst continuedefaultdo double elseenumextern floatfor gotoif int longregister return shortsigned sizeofstatic structswitchtypedefunionunsignedvoidvolatilewhile 十二、#define 定义常量和宏 12.1#define 定义常量
#include(stdio.h)#define c 100int main(){printf("%d\n", c);int d = 100;printf("%d", d);return 0;}
打印结果:
12.2#define 定义宏:
#include#define add(x,y)(x)+(y)//宏名参数 宏体int main(){int a = 10;int b = 20;int c = add(a, b);//替换成int c=((a)+(b))printf("%d", c);return 0;}
打印结果:
十三、指针
13.1 想了解指针需要先了解一下内存:内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。 所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
内存单元有相对应的编号,这一个编号就是地址,这个地址也叫做指针,也就是说地址就是指针,用来储存地址的变量叫指针变量。
如何取出变量的地址呢?就要用到前面介绍的取地址符&
#include int main(){ int num = 10; #//取出num的地址。注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址) printf("%p\n", &num);//打印地址,%p是以地址的形式打印 return 0; }
&num的作用就是取出创建的变量num的地址
内存 | |
一个字节 | 0xFFFFFFFF |
一个字节 | 0xFFFFFFFE |
一个字节 | 0xFFFFFFFD |
0x0012FF47 | |
0x0012FF46 | |
0x0012FF45 | |
0x0012FF44 | |
一个字节 | 0x00000002 |
一个字节 | 0x00000001 |
一个字节 | 0x00000000 |
变量num的类型是int类型,其大小为4个字节,红色的部分为num的地址,打印的地址就是读取到num的第一个地址。
变量取出来后如果需要储存,就需要定义指针变量:
int num = 10;int* p=&num;//int说明指针变量p所指的变量num是一个整形
指针的具体使用:
#includeint main(){int a = 10;int* p= &a;*p =20;printf("%d\n", a);return 0;}
打印结果:
定义一个整型的变量a=10,用&a取出变量a的地址并放入指针变量p中,指针变量p的类型(也就是a的类型)是整型,用解引用符找到p变量的指向对象(a),并对指向对象重新赋值20,打印a的结果时发现打印的就是第二次赋值的20。13.2指针变量的大小,用到前面所介绍的sizeof
#includeint main(){printf("%d\n", sizeof(char *));printf("%d\n", sizeof(short *));printf("%d\n", sizeof(int *));printf("%d\n", sizeof(double *));return 0; }
打印结果:
结论:指针大小在32位平台是4个字节,64位平台是8个字节。
十四、结构体:结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。 比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。 这里只能使用结构体来描述了,具体就是把单一的类型组合在一起。
#includestruct xs//定义结构体类型要用struct,这个类型名叫xs(自己定义){char name[20]; //叫做结构体成员,其中要放的是字符串,需要将字符串放到字符串数组里面int age ;char sex[10];char id[15];};void project(struct xs* dy) //自定义函数project,将s的地址赋给dy,*dy表示的是s{printf("%s %d %s %s\n", (*dy).name, (*dy).age, (*dy).sex, (*dy).id);printf("%s %d %s %s\n", dy->name, dy->age, dy->sex, dy->id);}int main(){struct xs s = { "张三", 21 ," 男 ","20209999" };//s为创建的结构体变量,访问其对象时,需要加.这个操作符printf("%s %d %s %s\n", s.name, s.age, s.sex, s.id);project(&s); //自定义函数,取s的地址给自定义的函数return 0;}
打印结果:
上面展示了结构体的三种打印方式,其中放在project()函数里面的是利用指针打印,外面的那一种是直接打印不用创建指针。在函数内的打印方式和外面的那一种差别不大。
函数外:打印时填入需要打印的类型,最后在后面写上 结构体变量(s).字符串的变量名(name、age、sex、id) 这种格式打印
函数内:将结构体变量名用指针来代替,只是改变的形式,但没改变本质,最后将操作符“.”改成 “->”就行