初阶C语言(一)

一、初识C语言

1.什么是C语言

C语言是一门计算机语言。
 

1.2什么是计算机语言

计算机语言是人和计算机语言交流的语言,比如C++,JAVA等等。
 

1.3计算机语言的发展

最早期是二级制语言(只有0和1) 10111110101010100011010100 某个二级制序列有一定含义,多个二级制序列连在一起形成一段代码。 给一个二进制起一个名字 101101 + ADD – 助记符 表示加法就可以用ADD,这种语言称为汇编语言。 后来发明高级语言,一条语言可以相当于多条汇编语言 B语言—>C语言—>C++(高级语言)

2.第一个C语言程序

创建工程—>创建文件—>编写代码 .c 源文件 .h 头文件

#include <stdio.h> //调用库函数
int main()  //主函数-程序的入口,有且仅有一个主函数
{   //int是整型的意思,main前面的int表示main函数调用返回一个整型值
    printf(hello,world);  //在屏幕上输出hello,world 库函数需要调用
    return 0; //返回 0
}

 

第一次运行成功但是一闪而过

首先右击项目

调试1.png

找到属性

调试2.png

在左侧找到链接器中的系统,然后将子系统设置为控制台

调试3.png

3.数据类型

分类 类型 大小(byte) 描述
数据类型 char 1 字符数据类型
short 2 短整型
int 4 整型
long 4 长整型
long long 8 更长整型
float 4 单精度浮点型
double 8 双精度浮点型

 

 

举个例子:

#include <stdio.h>
int main()
{
    char ch = 'A';	//将字符A存储到ch变量中
    printf("%c\n",ch);
    rturn 0;
}        
    

由单引号”引起来的叫字符,如第四行。
其中char表示数据类型,ch是创建的变量表示向内存申请一部分空间来存储。
第五行%c表示打印字符格式的数据。

 

C语言格式字符

%c 单个字符
%d 十进制整数(int)
%ld 十进制整数(long)
%f 十进制浮点数(float)
%lf 十进制浮点数(double)
%o 八进制数
%s 字符串(char)
%u 无符号十进制数(DWORD)
%x 十六进制数(0x00000)

 

4.变量和常量

4.1定义变量

int age = 20; 定义整数型变量
char ch = ‘w’; 定义字符型变量

4.2变量的分类

全局变量和局部变量

#include <stdio.h>
int num2 = 10;	//全局变量-定义在{}代码块外面
int main()
{
    int num1 = 5;	//局部变量-定义在代码块内部
                    //局部变量和全局变量相同时局部变量优先
    return 0;
}

还有一种全局变量是新建一个项目

这时我们发现上面会出现两个项目,然后我们打开新建的项目定义一个新的变量a

然后我们返回原来的项目发现无法直接引用a,这时我们需要用一个关键字extern声明一下才能使用

这时我们打印a输出结果为5

 

全局变量可以在全部范围内使用
局部变量只能在定义的代码块内使用

 

定义变量不能随用随定义,要在开始统一定义变量,不然可能报错。

 

4.3常量的分类

  • 字面常量
  • const 修饰的常变量
  • #define 定义的标识符常量
  • 枚举常量
#include <stdio.h>
#define max 10	//定义标识符常量,此时max等于10且不能修改
int main()
{
    3.14;
    100;	//这种直观写出来的值叫做字面常量
    const int num = 4;	//const赋予变量num常属性,此时num无法修改
    printf("%d",num);	//num本质还是变量只是具有常属性
    num = 8;
    printf("%d",num);	//此时会报错
    return 0;
}
    

 

#include <stdio.h>
//枚举常量--->一一列举
//例如性别:男,女
//枚举关键字  enum
enum sex
{
    MALE,
    FEMALE
};
int main()
{
    enum sex s = FEMALE;
    printf("%d",MALE);	//输出结果为0且不可改变
    printf("%d",FEMALE);	//输出结果为1且不可改变
    return 0;
}
    

 

5.输入数据

输入数据使用scanf()函数

#include <stdio.h>
int main()
{
    int num1 = 0;
    int num2 = 0;
    int num = 0;
    scanf("%d%d",&num1,&num2);	//&取地址符号
    num = num1 + num2;
    printf("%d",num);
}
    

 

注意

在VS编译器中scanf()函数被认为是不安全的使用会报错,可以在代码最上方添加一段代码让警告失效。

#define _CRT_SECURE_NO_WARNINGS 1

默认添加此段代码
首先找到安装VS编译器的路径找到newc++file.cpp文件

然后编辑文件输入#define _CRT_SECURE_NO_WARNINGS 1 保存,如果不能编辑将文件复制到别的地方在编辑,之后替换原文件。

 

6.字符串、转义字符、注释

6.1字符串

“hello world”
这种由双引号引起来的一串字符称为字符串字面值,或者简称字符串。
注:字符串的结果标志是一个\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;
}
    

 

此时输出结果为

使用编译器调试发现arr1有四个元素,arr2只有三个元素

在数组arr2后面加上一个0,那么最后输出结果相同。

 

实际上字符串”abc”放到数组arr1里面的元素为’a’ ‘b’ ‘c’ ‘\0’末尾默认有一个\0表示字符串的结束标志。arr2数组后面没有结束标志所以继续打印一些随机值。

 

表中a对应97为ASCII码值

ASCII表

6.2转义字符

“\”加上数字或者字母将会改变其含义

转义字符 意义 ASCLL码值(十进制)
\a 响铃(BEL) 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\’ 代表一个单引号 039
\” 代表一个双引号字符 034
\ 代表一个反斜线字符”’ 092
\? 代表一个问号 063
\0 空字符(NUL) 000
\ddd 1到3位八进制数所代表的任意字符 三位八进制
\xhh 十六进制所代表的任意字符 十六进制

 

6.4注释

作用

代码中不需要的代码可以直接删除,也可以注释掉。
代码中有些代码比较难懂,可以加一下注释文字。
注释的内容在运行的过程中直接跳过,不影响运行。

 

单行注释

//注释内容

2.多行注释

注释内容*/
在多行注释中注意不能嵌套

我们在int a之前和printf之后用了一组多行嵌套,但是在int main和}后也用了一组多行注释,这时我们发现有一部分代码没有被注释进去,所以多行代码注意不能嵌套。

 

7.选择语句

比如说好好学习能考好大学,然后提出问题你是否要好好学习,这就是选择。
在编程中会遇到很多需要选择的问题,因此我们需要用选择语句来解决。

#include <stdio.h>
int main()
{
    int a;
    printf("你要好好学习吗?\n");
    printf("输入1表示是,输入0表示否");
    scanf("%d",&a);
    if(a==1)
        printf("好大学等着你");
    else
        printf("回家卖地瓜");
    return 0;
}
    

如上if便是一个选择语句,首先提问,然后让用户回答,如果a的值为1,那么输出”好大学等着你”,如果a的值不为1,那么输出”回家卖地瓜”。

8.循环语句

生活中有些事情需要一直做,比如说学习,但是总会有条件跳出循环,比如说考上好大学。(当然只是举个例子,考上好大学就不学习不可能的,生命不止,学习不休,何以解忧,唯有学习)

#include <stdio.h>
int main()
{
    int i = 0;	//今天是学习的第0天
    while(i < 999)	//学到999天跳出循环
    {
        i++;
        printf("你学的还不够多\n");
    }
    printf("恭喜你");	//跳出循环
    return 0;
}
    

如上定义i等于0,当<999时会一直循环代码,只有当i>=999时才会跳出循环,当然也要注意不要写成没有终止的循环代码。

后面还有for,do while循环,后面再说。

 

9.函数

我们平常计算两个数的求和需要用到+,每次求和时都会需要重新引入,那么我们可以定义一个函数,我们每次只需要引用一个函数就可以计算两个数的和。

#include <stdio.h>
int Add(int x,int y)	//定义x和y的类型
{
    int z = 0;
    z = x + y;
    return 0;
}
int main()
{
    int a = 10;
    int b = 5;
    int sum = 0;
    sum = Add(a,b);
    printf("%d",sum);
}
    

在上述代码中我们引用Add这个函数,在调用函数的时候,a的值赋给x,b的值赋给y,然后定义z存储x+y的和,最后返回z,这时Add(a,b)的值就为z的值,然后赋给sum,最后sum的值就是a+b。

 

10.数组

C语言中定义数组是一组相同类型元素的集合。在内存中的存储具有连续性。

定义:

int arr[10] = {1,2,3,4,5,6,7,8,9,10}; //定义一个整数型数组,最多放10个元素

#include <stdio.h>
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    printf("%d\n",arr[0]);
    return 0;
}
    

如上代码我们定义一个整数型数组,其中含有十个元素,当我们要访问其中一个元素时需要用到下标,数组内元素的下标是从0开始的,也就是第一个元素的下标为0。如上我们打印第一个元素的值,所以输出为1。

我们也可以借助循环来实现依次打印元素里面的值

#include <stdio.h>
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    while(i < 10)
    {
        printf("%d\n",arr[i]);
        i++;
    }
    return 0;
}
    

 

11.操作符

算术操作符

+ 加号
减号
* 乘号
/ 除号
% 取余 5%2=1

 

移位操作符

>> 向右移
<< 向左移

移(二进制)位操作符
例:

#include <stdio.h>
int main()
{
    int a = 1;
    a << 1;	//向左移动一位
    return 0;
}
    

在第四行代码中定义变量存储1,其中int向内存申请四个字节所以二进制存储形式应该如下
00000000000000000000000000000001

其中向左移一位表示上面数据最左边的一位数丢弃,在最右边补上一位变成
00000000000000000000000000000010

移动完之后如果没有重新赋值其本身不变。

 

位操作符

在C语言中0为假1为真

& 按位与(二进制位只要有假就保留假,同时为真则为真)
| 按位或(二进制位只要有真就保留真,同时为假则为假)
^ 按位异或(对应的二进制位相同则为0,对应的二进制位相异则为1)
#include <stdio.h>
int main()
{
    int a = 3;
    int b = 5;
    int c = 0;
    c=a & b;
    printf("%d\n",c);
    c=a | b;
    printf("%d\n",c);
    c=a ^ b:
    printf("%d\n",c);
    return 0;
}
    
按位与 按位或 按位异或
3的二进制 0 1 1 0 1 1 0 1 1
5的二进制 1 0 1 1 0 1 1 0 1
结果 0 0 1 1 1 1 1 1 0
转成十进制 1 7 6


 

赋值操作符

= 赋值
+= 加上之后再赋值 a=a+10 —> a+=10
-= 减去以后再赋值 a=a-10 —> a-=10
*= 乘完以后赋值
/= 除完以后赋值
^= 按位异或后赋值
|= 按位或后赋值
&= 按位与后赋值
>>= 向右移后赋值
<<= 向左移后赋值

 

单目操作符

! 逻辑反操作
负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
前置,后置–
++ 前置,后置++
* 间接访问操作符(解除引用操作符)
(类型) 强制类型转化

 

解释

!

C语言中0表示假,非0表示真

#include <stdio.h>
int main()
{
    int a = 10;
    printf("%d",!a);
    return 0;
}
    

因为a等于10为非零为真,所以逻辑反操作符!将a转化为假(变成0)所以输出结果为0。

 

sizeof

#include <stdio.h>
int main()
{
    int a = 10;
    int arr[10]={0};
    printf("%d",sizeof(a));	//输出为4,变量可以去括号
    printf("%d",sizeof(int));	//输出为4,类型不能去括号
    printf("%d",sizeof(arr));	//输出为40,四个整型元素
    printf("%d",sizeof(arr)/sizeof(arr[0]));	
    //计算有多少个元素,总空间/一个元素占用空间大小
    return 0;
}
    

sizeof 计算的是变量/类型所占空间的大小,单位是字节。

 

~

#include <stdio.h>
int main()
{
    int a = 0;	//4个字节,32个bit位
    int b = ~a;	//b是有符号的整型,如果有符号二进制最高位为符号,1为负号
    //~按(二进制)位取反
    //000000000000000000000000000000000000000000
    //111111111111111111111111111111111111111111
    printf("%d",b);	//打印的是原码
    return 0;
}
    

原码、反码、补码

负数在内存中存储的时候,存储的是二进制的补码
正数的原码、反码、补码相同
负数的原码是直接按照正负二进制序列写出来的,反码是除了符号位取反,补码是反码加一得到的。
在计算机系统中,数值一律用补码来储存。

如上代码第八行,此时取反后存储的为补码,将补码转换成原码后为
100000000000000000000000000000000000000001
第一位为符号所以输出结果为-1

++/–

#include <stdio.h>
int main()
{
    int a = 10;
    int b = a++;	//后置++先赋值后自增1
    printf("%d,%d",a,b);	//输出结果为11,10
    return 0;
}
    

如果前置++/–先自增/减1,然后再赋值。

 

(类型)

#include <stdio.h>
int main()
{
    int a = (int)3.14;	
    return 0;
}
    

在第三行如果没有加(int)会发生警告,因为3.14是浮点型,转化成整型会发生数据丢失,这里加上(int)把3.14强制转化成整型。

单/双/三目操作符区分

a+b; 加号两边有两个操作数所以称为双目操作符

只有一个操作数的称为单目操作符

有三个操作数的称为三目操作符

 

关系操作符

> 大于
>= 大于等于
< 小于
<= 小于等于
!= 用于测试“不相等”
== 用于测试“相等”

 

逻辑操作符

&& 逻辑与
|| 逻辑或

 

条件操作符

exp1?exp2:exp3
exp意思是表达式,如果表达式1的结果为真,那么表达式2执行,表达式2的结果为整个表达式的结果,如果为假执行表达式3,表达式3的结果为整个表达式的结果。

#include <stdio.h>
int main()
{
    int a = 3;
    int b = 5;
    int c = 0;
    c = a > b ? a : b;
    printf("%d",c);
    return 0;
}
    

其中a>b表达式为假,所以b的值赋给c,所以输出结果为5。

 

逗号表达式(所有运算符中级别最低)

exp1,exp2,exp3,……expN

整个表达式的值为最后一个表达式的值

如:
a=(3+7,10*3);
a的值为30
a=(a=3,3+3);
a最后的值为6

 

下标引用、函数调用的结构成员

. 这个等会说
-> 这个也等会说
[ ] 数组下标引用操作符,下标从0开始
( ) 函数调用操作符

例:
int a = 10;
int b = 20;
int sum = add(a,b); 此时add后面的括号为函数调用操作符(函数知识)

 

C语言符号优先级

 

12.常见关键字(C语言内置)(不能与变量名冲突)

auto 自动

在C语言中定义局部变量
int a = 10;其作用周期是一个代码块{},当运行完这个代码块时这个局部变量自动销毁,因为前面隐藏一个关键字auto,原代码应为
auto int a = 10;
由于每个局部变量都有所以省略。

 

break 循环中停止循环,switch case语句中
case switch case语句中
char 字符类型
const 常量修饰
continue 循环继续
default 默认
do do while循环
double 双精度浮点型
else if else语句
enum 枚举
extern 引入外部符号(详见全局变量,同理应用于函数详见static解析)
float 单精度浮点型
for for循环
goto goto语句
if if语句
int 整型
long 长整型
register 寄存器关键字

register int a = 10;
建议把a放进寄存器,是否放入由编译器判断决定
在CPU处理数据时,CPU的处理速度是非常快的,所以首先向寄存器中拿取数据,如果寄存器没有再向高速缓冲器拿取,以此类推到内存,然后硬盘。
从硬盘到寄存器运行速度越来越快,相应的储存空间越来越小。
因此当编程中某个元素应用频繁时可以用register建议放进寄存器。

return 返回
short 短整型
signed 有符号 平常定义int,short等都是有符号的默认signed省略
sizeof 计算大小
static 静态
struct 结构体关键字
switch switch case关键字
typedef 类型定义
union 联合体/共用体
unsigned 无符号的 unsigned int a = 10;
viod
viod
volatile C语言断位
while do while循环

 

typedef 类型定义–类型重定义

unsigned int num = 20; 定义一个无符号整型变量
此时定义类型太长可以用typedef重定义、
typedef unsigned int u_int; 相当于把unsigned in重新定义一个名字u_int
如果放在所有函数之外,它的作用域就是从它定义开始直到文件尾;
如果放在某个函数内,定义域就是从定义开始直到该函数结尾。

 

static 静态

修饰局部变量时

#include <stdio.h>
void test()
{
    int a = 1;
    a++;
    printf("a=%d\n",a);
}
int main()
{
    int i = 0;
    while(i < 5)
    {
        test();
        i++;
    }
    return 0;
}
    

上述代码中首先从第10行开始,先定义i=0,然后进入while循环,引入test()函数。

在test函数里面定义a=1,然后a自增1,再然后打印a的值。之后返回主函数i自增1,由于i<5,i每次自增1,所以循环执行五次,之后的每次循环a由于在函数周期结束后自动销毁,所以每次进入test函数后a都要重新定义赋值1,因此最后输出结果为

这时如果我们在test函数定义a前面加上static变成
static int a = 0;
此时输出结果为

这说明a没有被销毁,并且继承了原来的值,跳过了test函数里面对a的定义和赋值。
所以static修饰局部变量时,使局部变量的生命周期变长。

 

修饰全局变量时

当static修饰第二种全局变量时(从另一个源文件定义变量,然后用extern声明使用),从原来的源文件无法使用另一个源文件定义的变量了

所以static修饰全局变量时,改变了变量的作用域,让静态的全局变量只能在自己所在的源文件内部使用。

 

修饰函数时

当修饰函数时和全局变量类似
如图在第一个源文件内输入以下代码

(注意extern声明函数的格式)
第二个源文件内输入函数代码

这时我们能正常运行输出a+b的结果为8
此时如果我们把第二个源文件中定义函数前面加上static修饰
int add(int x,int y)改成
static int add(int x,int y)
这时我们再运行第一个源文件时会报错,这是因为static修饰函数改变了函数的链接属性(函数具有外部属性,只要在其他源文件内声明就可以应用函数),使函数外部链接属性变为内部链接属性,此时函数只能在定义函数本身的源文件使用。

 

#define定义常量和宏

定义常量详见常量

定义宏

前面我们学习函数时可以用函数解决比较大小的问题,同样我们可以用宏解决。

#include <stdio.h>
        #define max(x,y) (x>y?x:y)
int main()
{
    int a = 10;
    int b = 15;
    int c = max(a,b);
    printf("%d",c);
    return 0;
}
    

在第7行我们定义一个函数max想要求a和b的最大值,但是第二行我们定义了宏用一个条件操作符代替了max从而计算a和b的最大值。

上面的#define是用后者替换前者,其中里面a的值赋给x,b的值赋给y。

 

13.指针

内存

常见电脑有32位和64位,以32位为例,32位相当于有32根地址线/数据线。32位比特共有2^32个编号,也就是这么多个地址,每个地址都有相应的空间,如果每个空间只有1bit那么这个内存便是0.5g(空间大小乘地址数)。

假设一个32位电脑,一个空间为一个字节。那么定义

int a = 10; 需要申请四个字节也就是要申请四个空间

#include <stdio.h>
int main()
{
    int a = 10;
    &a;		//取地址
    printf("%p\n",&a);	//打印a的地址
    return 0;
}
    

这时候我们会得到一个十六进制的数字,将十六进制转化成二进制就能得到地址。

 

同样地址也能存到变量中,这种变量称为地址变量。
int*p = &a; //将整型a的地址存到p中

 

#include <stdio.h>
int main()
{
    int a = 10;
    int*p = &a;
    *p = 20;	//*-解引用操作符
    printf("%d\n",a);
    return 0;
}
    

当我们运行上面代码时输出结果为20。

从第四行开始,我们首先创建一个变量a的值为10,然后我们创建一个地址变量p存储a的地址。然后第六行我们解引用操作符解析a的地址,相当于把20放到a的地址中,此时a的值就变为了20。

 

指针变量的大小

我们定义一个指针变量存储地址,此时指针变量也需要一个内存空间存储。指针变量是存储某个地址,在32为电脑中一个地址就是一个32位的二进制数,也就是4个字节,所以32位电脑一个指针变量的大小为4个字节。同理64位电脑一个指针变量大小为8个字节。

 

14.结构体

当我们描述一本书时,我们很难用C语言的数据类型描述,我们可以用struct结构体自己定义一个数据类型。

#include <stdio.h>
struct book
{
    char name[20];	//定义名字
    short price;	//定义价格
};	//注意结构体后面有个分号
int main()
{
    struct book b1 = {"C语言",20};	//定义的新的数据类型定义变量
    printf("书名:%s\n",b1.name);	
    printf("价格:%d\n",b1.price);
    b1.price = 15;
    printf("修改后价格:%d\n",b1.price);
    return 0;
}
    

在第10行我们打印b1.name中的.为结构体成员运算符,表示引出b1结构内的成员。

输出结果为

我们可以看到可以用.号来运算结构体内的成员,并且可以修改其中的值。
当我们要把b1存到指针变量里面是我们需要指向struct book
struct book*pb = &b1;
当我们要用指针来打印书名和价格时可以
printf(“%s\n”,(*pb).name); //*pb就指向b1
printf(“%d\n”,(*pb).price);
同样我们也可以用->(指向结构体成员运算符)来指向结构体内部的成员
printf(“%s\n”,*pb->name);
printf(“%d\n”,*pb->price);

 

.应用到结构体变量来找到成员
->应用到结构体指针来找到成员

 

上面我们演示如何改变书的价格,但是如果我们按照相同的办法改变书名结果会显示报错,因为书的价格是一个变量,而书的名字是一个数组。数组的的本质是一个地址,如果我们想要改变书的名字那么需要用到strcpy函数。

strcy(地址,数值) 字符串拷贝函数,属于库函数,需要引用头文件string.h
strcpy(b1.name,”C++”);
我们添加这一段代码以后,表示将字符串C++拷贝到此地址中。然后我们就可以改变书名。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇