栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

第1节-初识c语言

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第1节-初识c语言

目录

1.第一个c语言程序(hello word)

2.数据类型

2.1.数据的类型

2.2.每种类型占用内存的大小

2.3.类型的使用

3.变量、常量

3.1.定义变量的方法

3.2.变量的分类

3.3.变量的使用

3.4.变量的作用域和生命周期

3.4.1.作用域

3.4.2.生命周期

3.5.常量

3.5.1.字面常量

3.5.2.const 修饰的常变量

3.5.3.#define 定义的标识符常量

3.5.4.枚举常量

4.字符串+转义字符

4.1.字符串

4.2.转义字符

5.注释

6.选择语句(if语句为例,简单介绍,后面会细说)

7.循环语句(while语句为例,简单介绍,后面会细说)

8.函数

9.数组

9.1.数组的定义

9.2.数组的下标

9.2.1.数组下标的定义

9.2.2.使用下标访问数组

9.3.数组的使用

10.操作符(简单介绍为主,后面会细说)

10.1.算数操作符

10.1.1.除操作符

10.2.2.取模(余)操作符

10.2.移位操作符

10.3.位操作符

10.4.赋值操作符

10.5.单目操作符

10.5.1.感叹号操作符

10.5.2.负号操作符(正号同理)

 10.5.3.sizeof操作符

10.5.4.~(按位取反)操作符

10.5.5.++、--操作符

10.5.6.(类型)  强制类型转换操作符

10.6.关系操作符

10.7.逻辑操作符

10.8.条件操作符

10.9.逗号表达式

10.10.下标引用、函数调用和结构成员

10.10.1.下标引用操作符

10.10.2.函数调用操作符 

11.常见关键字(主要介绍typedef和static,其他的后面会讲)

11.1.关键字typedef

11.2.关键字static

11.2.1.修饰局部变量

11.2.2.修饰全局变量

11.2.3.修饰函数

12.#define定义常量和宏

13.指针

13.1.内存

13.2.指针变量的大小

14.结构体

14.1.结构体的类型定义及使用

操作符的使用">14.2.指针变量应用于结构体及->操作符的使用


1.第一个c语言程序(hello word)

代码:

#include
int main()
{
	printf("hello wordn");
	return 0;
}

1.main(主函数)是程序的入口,程序是从main函数的第一行开始执行的。main函数有且仅有一个。

2.int是整型的意思,表示main函数运行结束返回一个整型的值,return 0中0是一个整数,在main函数结束时被返回,二者相互呼应。

3.printf是一个库函数,库函数的使用得包含一个头文件stdio.h。因此在开始输#include

4.stdio.h中:std为标准,i为input是输入,o为output是输出,所以把stdio.h叫做标准输入输出头文件。


2.数据类型

2.1.数据的类型
char          // 字符数据类型 short         // 短整型 int             // 整型 long          // 长整型 long long      // 更长的整型 float         // 单精度浮点数 double       // 双精度浮点数
注:float定义时,在数字后面加一个f,否则默认为double类型。

2.2.每种类型占用内存的大小

代码:

#include
int main()
{
	printf("%dn", sizeof(char));
	printf("%dn", sizeof(short));
	printf("%dn", sizeof(int));
	printf("%dn", sizeof(long));
	printf("%dn", sizeof(long long));
	printf("%dn", sizeof(float));
	printf("%dn", sizeof(double));
	printf("%dn", sizeof(long double));
	return 0;
}
运行结果:
1
2
4
4
8
4
8
8
总结:
char1
short2
int4
long4
long long8
float4
double8

1.sizeof:用来计算变量或者使用类型创建的变量的大小,单位是字节。 2.%d:打印一个十进制的整数。 3.计算机中的单位:
11111111

                                                        8比特(bit)=1字节(byte)

 4.short类型占用两个字节,16个比特,表示的范围:-1即0—65535。其它算法类似。

 5.c语言中规定sizeof(long)>=sizeof(int)。图中便是等于的情况。

2.3.类型的使用
#include
int main()
{
	char ch = 'w';
	int weight = 120;
	return 0;
}

1.字符需使用单引号引起来。


3.变量、常量

c语言中为了描述变化的值,使用变量,描述不变的值,使用常量。

3.1.定义变量的方法
	int age = 150;
	float weight = 45.5f;
	char ch = 'w';

1. 变量在创建的时候不初始化是一种不好的代码风格。当一个局部变量不初始化的时候,它的值是随机的。

3.2.变量的分类

  局部变量

 全局变量

定义:一个{ }就是一个代码块,在代码块内部定义的变量就是局部变量,在代码块外部定义的变量就是全局变量。

#include
int a = 100;  //全局变量
int main()
{
	int a = 10;  //局部变量
	printf("%dn", a);

	return 0;
}

 1.局部变量和全局变量的名字冲突的情况下,局部优先。

    例如,上图程序代码运行结果为a=10。

3.3.变量的使用

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include 
int main()
{
	int num1 = 0;
	int num2 = 0;
	int num = 0;
	printf("输入两个操作数:>");
	scanf("%d %d", &num1, &num2);
	num = num1 + num2;
	printf("sum=%dn", num);

	return 0;
}
运行结果:
输入两个操作数:>1 1
sum=2
1.scanf是c语言提供的一个输入函数。此时当程序报错时(如下图所示),报错中讲到的scanf_s的函数是vs编译器提供的,不是c语言自己的,在其他编译器(gcc,clang)下就没scanf_s函数, 也不认识这个函数,当你在代码中使用了scanf_s函数,你的代码在其他的编译器下就没办法正确编译,降低了代码的跨平台性,所以建议写代码时尽量使用标准c提供的功能和函数。 解决方法:将#define  _CRT_SECURE_NO_WARNINGS 1写在第一行。 注:若不想每次都在代码开头定义,可在电脑中搜索一个文件:newc++file.cpp。找到后将定义的内容写进去即可。(直接编辑,系统会提示没有权限打开文件,将文件拖入桌面进行编辑并保存再拖入之前文件夹即可)

 2.符号&:取地址。

3.4.变量的作用域和生命周期

3.4.1.作用域
作用域( scope )是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效 / 可用 的 而限定这个名字的可用性的代码范围就是这个名字的作用域。 1. 局部变量的作用域是变量所在的局部范围。 2. 全局变量的作用域是整个工程。
代码:
#include 
int main()
{
	int a = 10;
	{
		int b = 20;
		printf("%dn", b);
	}
	printf("%dn", b);
	return 0;
}

运行结果:

结果出错:“b”: 未声明的标识符

3.4.2.生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段 1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。 2. 全局变量的生命周期是:整个程序的生命周期

3.5.常量
C 语言中的常量和变量的定义的形式有所差异。 C 语言中的常量分为以下以下几种:     字面常量     const 修饰的常变量       #define 定义的标识符常量     枚举常量

3.5.1.字面常量
100;
3.14;
"abc";
'w';

3.5.2.const 修饰的常变量

代码:

#include 
int main()
{
	const int num = 10;
	printf("%dn", num);
		num = 20;
	printf("%dn", num);

	return 0;
}
运行结果: 结果出错:左值指定 const 对象 1.当有一个变量不想被别人修改时便可以加上const进行保护。 2.虽然const修饰的变量是不能修改的,但本质上还是个变量。 如下图,程序运行会报错“应输入常量表达式”。 
const int n=100;
int arr[n]={0};

3.5.3.#define 定义的标识符常量
#define MAX 100
int main()
{
 int a=MAX;
 int arr[MAX];
 printf("%dn",a);
 return 0;
}

1.define定义的标识符常量一般习惯大写。

3.5.4.枚举常量

枚举这种类型的可能取值就是枚举常量。

#include 
enum sex
{
	MALE,
	DEMALE,
	SECRET
};

int main()
{
	enum sex s = MALE;
    printf("%dn",MALE);
    printf("%dn",FEMALE);
    printf("%dn",SECRET);
	return 0;
}


4.字符串+转义字符

4.1.字符串

字符: 'a'   '#'

字符串: "abc"    "a"    ""(空字符串)

这种由双引号( Double Quote )引起来的一串字符称为字符串字面值( String Literal ),或者简称字符串。
把字符串放在字符数组中,而不能将字符串赋值给一个字符,如下图。
char ch="abc";      //错误
char arr[]="abc";   //正确

1.字符串的末尾其实隐藏一个‘’,‘’是字符串的结束标志。下图arr2后没有‘’,所以电脑会一直往下打印,直到有‘’才结束。

 2.字符串的结束标志是一个 的转义字符。在计算字符串长度的时候 是结束标志,不算作字符串内容。

3.在算字符串字符时,‘’算作一个字符。如下图中:arr1占4个字符,arr2占3个字符,arr3占4个字符。

代码:
#include 
#include 

int main()
{
	char arr1[] = "abc";
	char arr2[] = { 'a','b','c' };
    char arr3[] = { 'a','b','c' ,''};

	printf("%sn", arr1);
	printf("%sn", arr2);
	printf("%sn", arr3);

    printf("%dn",strlen(arr1));
    printf("%dn",strlen(arr2));
    printf("%dn",strlen(arr3));

	return 0;
}

运行结果:

abc
abc烫烫烫烫蘟bc
abc
3
15
3

监视代码结果:

 注:1.%s 指定打印字符串,%c指定打印字符。

        2.strlen函数:求字符串长度的函数。在用到strlen函数时,需要#include头文件。

4.2.转义字符

转义字符就是转变原来的意思。 转义字符写在字符串中时不用单引号引,但是要是单独用的话需要用单引号,如上面的''。

下面看一些转义字符 

转义字符 释义
?在书写连续多个问号时使用,防止他们被解析成三字母词
' 用于表示字符常量 '
用于表示一个字符串内部的双引号
\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
a 警告字符,蜂鸣
b 退格符
f 进纸符
n 换行
r 回车
t 水平制表符
v 垂直制表符
ddd ddd 表示 1~3 个八进制的数字。如: 130 X
xdd dd 表示 2 个十六进制数字。如: x30 0
 

printf("(hehe??)");                   //打印(hehe??)
printf("%c",''');                      //打印'
printf("%s",""");                      //打印"
printf("c:\test\104\test.c");        //打印c:test104test.c
printf("aaaa");                     //电脑蜂鸣
printf("%cn",'130');    //8进制的130转化成的10进制数88作为ASCII值所对应的符号:X
printf("%cn",'x30');    //16进制的30转化成的10进制数48作为ASCII值所对应的符号:0 

 练习:

求下列函数的输出值。

int main()
{
printf("%dn",strlen("c:test628test.c"));

 return 0;
}

答案:

14

5.注释
注释有两种风格: 1.C语言风格的注释 缺陷:不能嵌套注释    优点:可以一次注释多行 2.C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行
注释的作用: 1. 代码中有不需要的代码可以直接删除,也可以注释掉。 2. 代码中有些代码比较难懂,可以加一下注释文字。

6.选择语句(if语句为例,简单介绍,后面会细说) 代码:
#include
int main()
{
	int input = 0;
	printf("你要好好学习吗?(1/0):");
	scanf("%d", &input);
	if (input == 1)
	{
		printf("好offern");
	}
	else
	{
		printf("卖红薯n");
	}

	return 0;
}

运行结果:

你要好好学习吗?(1/0):1
好offer
你要好好学习吗?(1/0):0
卖红薯

7.循环语句(while语句为例,简单介绍,后面会细说)
#include
int main()
{
	int line = 0;
	while (line < 20000)
	{
		printf("敲代码n");
		line = line + 1;
	}
	if (line >= 20000)
		printf("好offern");
	else
		printf("火候还不够n");
	return 0;
}

8.函数

c语言中,把一些独立的功能能够封装成一个独立的函数。

函数的特点就是简化代码,代码复用。

在前面变量的使用中我们实现了输入两个整数相加的功能,下面我们使用函数来实现该功能。

代码:

#include
int Add(int x, int y)
{
	int z = x + y;
	return z;
}

int main()
{
	int num1 = 0;
	int num2 = 0;
	int sum = 0;
	scanf("%d %d", &num1, &num2);
	sum = Add(num1, num2);
	printf("sum=%dn", sum);

	return 0;
}

运行结果:

1 2
sum=3

1.正常情况下,将函数放到主函数之前,一定要放在主函数之后的话,要先在主函数之前进行函数声明(以上图代码为例,将函数代码放在主函数之后,并在主函数之前加 int Add(int x, int y); 进行函数声明)

2.函数中int Add(int x, int y)中:Add为函数名;int x, int y为函数的形式参数;int为返回类型与后面的return z中z的类型相对应;函数中用大括号括起来的内容叫函数体,如下图所示。


9.数组
C 语言中给了数组的定义:一组相同类型元素的集合。

9.1.数组的定义

1.定义一个整形数组,最多放十个元素。 

int arr[10]={1,2,3,4,5,6,7,8,9,10};

2.定义一个字符数组,最多放五个元素。

char ch[5]={'a','b','c','d','e'};

注:

1.下面代码是不行的,因为“hello”后面隐含一个‘’是6个字符,改成char[6]即可。

char[5]="hello";

2.下面叫不完全初始化,系统默认没有初始化的元素均为0。

int arr[10]={0};    //初始化十个元素都为0
int arr[10]={1};    //初始化第一个元素为1,后面九个元素为0

9.2.数组的下标

9.2.1.数组下标的定义
  C 语言规定:数组的每个元素都有一个下标,下标是从 0 开始的,如下图

9.2.2.使用下标访问数组
数组可以通过下标来访问的。
代码1:
int arr[10]={1,2,3,4,5,6,7,8,9,10};
printf("%dn",arr[2]);

运行结果1:

3

9.3.数组的使用

代码:

#include

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	while (i <= 9)
	{
		printf("%d ", arr[i]);
		i = i + 1;
	}

	return 0;
}

运行结果:

1 2 3 4 5 6 7 8 9 10

10.操作符(简单介绍为主,后面会细说)

c语言包含了非常丰富的操作符,所以有人说:“c语言是非常灵活的”,甚至直接可以操作内存数据,可以直接操作二进制位。

10.1.算数操作符

+      -      *      /      %

/:除

%:取模(余)

10.1.1.除操作符

当除号左右两边都是整数时,结果只能是整数

当除号两边有小数时,结果才是小数

n=7/2       //结果是n=3
n=7.0/2     //结果是n=3.5

10.2.2.取模(余)操作符
n=7%2     //商3余1,结果为n=1

注:取模操作数只能作用于整数(整型),不能作用于小数(浮点数)。

例题:输入一个数,判断其是奇数还是偶数。

#include
int main()
{
	int n = 0;
	scanf("%d", &n);
	if (n % 2 == 1)
		printf("奇数n");
	else
		printf("偶数n");
	return 0;
}

10.2.移位操作符

<<          >>

<< :左移

>>:右移

移位操作符作用于一个数的二进制位

下面以左移为例(右移同理)

#include
int main()
{
	int a = 3;
	int b = a << 1;
	printf("%dn", b);
	return 0;
}

如上图,

a的二进制为:(下图该值为3)

00000000000000000000000000000011

a<<1的二进制为:(移完之后,该值为6)

00000000000000000000000000000110

所以上图代码运行结果为:

6

10.3.位操作符

&      ^      |

&:按位与        (对应的二进制位:有0即为0,全1才为1)

^:按位异或  (对应的二进制位:相同为0,相异为1)

|:按位或      (对应的二进制位:有1即为1,全0才为0)

以按位与为例,其他同理

int a=3;
int b=5;
int c=a&b;
printf("%dn",c);

 3的二进制位

00000000000000000000000000000011

5的二进制位

00000000000000000000000000000101

3&5的二进制位

00000000000000000000000000000001

所以该代码的运行结果为:

1

10.4.赋值操作符
=      +=      -=      *=      /=     &=      ^=       |=         >>=        <<=

以+=为例,其余同理

 以下两行代码功能相同

a=a+4;     //赋值
a+=4;      //复合赋值符

10.5.单目操作符
!           逻辑反操作 -           负值 +           正值 &           取地址     (后面再讲) sizeof       操作数的类型长度(以字节为单位) ~           对一个数的二进制按位取反 --           前置、后置 -- ++           前置、后置 ++ *           间接访问操作符 ( 解引用操作符 )    (后面再讲) ( 类型 )       强制类型转换

10.5.1.感叹号操作符
int a=10;
printf("%dn",!a);    //输出结果为0
int a=0;
printf("%dn",!a);    //输出结果为1

10.5.2.负号操作符(正号同理)
int a=10;
int b=-a;
printf("%dn",b);    //输出为-10

 10.5.3.sizeof操作符

计算的是变量或者类型所创建变量占据内存的大小,单位是字节。

int a=10;
printf("%dn",sizeof(a));     //4
printf("%dn",sizeof(int));   //4
printf("%dn",sizeof(10));    //4

10.5.4.~(按位取反)操作符

按位取反是操作二进制位(对数值的补码进行取反)

负整数的二级制有原码、反码、补码。

内存中存储的是二进制的补码。

按位取反操作符是对内存中的补码进行取反。

以-1为例:

原码:10000000000000000000000000000001

反码:11111111111111111111111111111110(原码的符号位不变,其他位按位取反得到反码)

补码:11111111111111111111111111111111(反码+1得到补码)

~ -1:00000000000000000000000000000000

int a=-1;
int b=~a;
printf("%dn",b);     //运行结果:0

10.5.5.++、--操作符

前置++: ++a           先++,后使用

后置++:a++            先使用,后++

前置--:  --a             先--,后使用

后置--:  a--             先使用,后--

int a=10;
int b=++a;
printf("%d %d",a,b);    //11 11   
int a=10;
int b=a++;
printf("%d %d",a,b);    //11 10   
int a=10;
int b=--a;
printf("%d %d",a,b);    //9 9   
int a=10;
int b=a--;
printf("%d %d",a,b);    //9 10   

10.5.6.(类型)  强制类型转换操作符
int n=(int)3.14;
printf("%dn",n);     //输出结果:3

10.6.关系操作符
> >= < <= !=         用于测试 “ 不相等 ” ==        用于测试 “ 相等 ”

10.7.逻辑操作符
&&        逻辑与 ||           逻辑或
int a=3;
int b=5;
if( (a==3) && (b==3) )
{
 printf("hehen");         //这里无输出结果,不输出hehe
}
int a=3;
int b=5;
if( (a==3) || (b==3) )
{
 printf("hehen");         //这里输出hehe
}

10.8.条件操作符

(表达式1 ) ? (表达式2) : (表达式3)

功能解释:

表达式1的结果为真,表达式2算,表达式3不算,表达式2的结果是整个表达式的结果。

表达式1的结果为假,表达式2不算,表达式3算,表达式3的结果是整个表达式的结果。

条件操作符可以简化if语句。如下图,两个代码实现功能相同,都是实现输入两个数,输出两个数的较大值功能。

if语句实现代码:

int a=0;
int b=0;
int max=0;
scanf("%d %d",&a,&b);
if(a>b)
    max=a;
else
    max=b;
printf("%dn",max);

条件操作符实现代码:

int a=0;
int b=0;
int max=0;
scanf("%d %d",&a,&b);
max=(a>b ? a : b);
printf("%dn",max);

10.9.逗号表达式

表达式1,表达式2,表达式3,......,表达式n

功能解释:

逗号表达式从左向右依次计算,整个逗号表达式的结果是最后一个表达式的结果。

int a=3;
int b=5;
int c=10;
int d=(a+2,b=a-3,c=b+4);
printf("%dn",d);     //运行结果:4     此时a=3,b=0,c=4,d=4

10.10.下标引用、函数调用和结构成员
[ ]                      ( )                   .  (后面再讲)                 -> (后面再讲)

[ ]:下标引用操作符

( ):函数调用操作符

10.10.1.下标引用操作符

以下图代码为例,下标引用操作符的操作数为arr和4。

int arr[10]={1,2,3,4,5};
printf("%dn",arr[4]);

10.10.2.函数调用操作符 

以下图代码为例,函数调用操作符的操作数为Add , 3 , 5(我们可以看出函数调用操作符的操作数不固定)

int Add(int x, int y)
{
	int z = x + y;
	return z;
}

int main()
{
 int sum=Add(3,5);
 printf("%dn",sum);
 return 0;
}

11.常见关键字(主要介绍typedef和static,其他的后面会讲)
auto        break         case        char        const         continue        default       do         double     else       enum        extern       float        for        goto        if         int         long        register     return         short        signed        sizeof         static       struct        switch        typedef      union   unsigned         void        volatile (先不讲,在linux中会讲)         while
注: 1.关键字是系统定义好的,不能自己创建。 2.关键字不能做变量名。 3.define不是关键字,是预处理指令。

1. auto:意思是自动,用来定义自动变量(变量自动创建,自动回收)

int main()
{
auto int a;
return 0;
}

实际上所有的局部变量都是auto的,因此auto关键字一般都是省略掉的。

2.循环语句中的:

     break: 终止,在循环中使用(while,for , do while),在选择结构switch也会用到。

    continue: 继续,在循环中使用。

    do: 在do while循环语句中使用。

    while:用于循环。

3.选择语句中的:

    case:  在switch语句中使用。

    default: 默认,在switch语句中使用。

     else:if else语句中用到。

     if:用于if语句。

     switch:用于switch语句。

4.数据类型:char   short   int   long   float   double

  应用于类型的(本身不是类型): signed     unsigned

signed int sum=100;       //有符号整型
unsigned int sum=100;     //无符号整型

5.const: 常属性,用于修饰变量或修饰指针。

6.三个可自定义类型:

  enum:枚举。

  struct:结构体。

  union:联合体。

7.extern:用于声明外部符号。

8.goto:用于分支或循环。

9.register: 寄存器。

补充:数据存储体系与CPU

CPU(中央处理器)在电脑中进行运算的器件。在早期,CPU处理速度和内存读写速度是匹配的,CPU进行运算是从内存里拿取数据,算完之后把数据放回去。后来随着技术的发展,CPU处理速度越来越快,内存读写速度跟不上,于是出现了高速缓存和寄存器。CPU直接在寄存器里拿数据,若寄存器拿不到数据,可以把高速缓存的数据与寄存器替换,而高速缓存的数据可以在内存里面替换。

int main()
{
register int a=10;   //将变量a放到寄存器里面去。
return 0;
}

注:

1.register是建议作用,建议编译器把变量放在寄存器里面去,最终到底有没有放进寄存器不是确定的,由编译器自己决定(若大量频繁的使用该建议的变量,编译器或许就把该变量放入寄存器)。 

2.register作用的变量(寄存器变量)不能取地址,即寄存器是不能取地址的,取地址是在内存中取的。

10. return: 是返回,在函数中使用。

11. void:无、空的意思。用于函数的返回类型,函数参数,修饰指针。

12.sizeof:用于判断变量或数据类型的字节大小。

13. static:静态的。

14.typedef:类型重定义

11.1.关键字typedef
typedef 顾名思义是类型定义,这里应该理解为类型重命名。
#include
typedef unsigned int u_int;
int main()
{
 unsigned int num1=100;
 u_int num2=100;          //两句代码意思相同,并且实现功能相同。

 return 0;
}

11.2.关键字static

static:静态的。

c语言中static可以修饰:

1.局部变量(修饰后叫做静态局部变量)

2.全局变量(修饰后叫做静态全局变量)

3.函数(修饰后叫做静态函数)

11.2.1.修饰局部变量

若static修饰局部变量,下面我们用两个代码,分别是未使用(代码1)和使用(代码2)static关键字修饰,对两个代码进行对比,进而解释static的功能。

代码1:

#include

void test()
{
	int a = 1;
	a++;
	printf("%d ", a);
}
int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	return 0;
}

运行结果1:

2 2 2 2 2 2 2 2 2 2     //十个2

代码2:

#include

void test()
{
	static int a = 1;
	a++;
	printf("%d ", a);
}
int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	return 0;
}

运行结果2:

2 3 4 5 6 7 8 9 10 11

注:void在这里表示不需要函数返回值。

根据结果,我们推测出:经过static进行修饰,每一次调用test函数,使用的a都是上一次函数调用留下的a。

补充:内存是一块比较大的存储空间,在使用内存的时候会划分出不同的功能区域。在学习编程语言的时候我们需要关注到以下几个区域:栈区、堆区、静态区,具体介绍如下图。

 结论:

1.上面代码中若a没有经过static修饰,那么它会存到栈区,而经过static修饰的话,它会存到静态区。

2.static修饰局部变量的时候,其实改变了变量的存储类型(栈区存储 - > 静态区),从而使得静态的局部变量出了自己的作用域也不会销毁,其实相当于改变了这个局部变量的生命周期(与全局变量一样,是程序的生命周期),但是其作用域不变还是原来的作用域,只是出了作用域,该变量不销毁。

11.2.2.修饰全局变量

 若static修饰全局变量,我们以下面两个代码进行对比,并进行解释。

无static修饰的代码:

有static修饰的代码:

注:

1.如果想使用来自其他文件(外部文件)的全局变量,先要声明一下。

2.extern是一个关键字,是专门用来声明外部符号的。

3.从这里我们可以看出,全局变量本身是具有外部链接属性的。

结论:

一个全局变量在整个工程的其他文件内部能被使用,是因为全局变量具有外部链接属性,当一个全局变量被static修饰的时候,这个变量的外部链接属性就变成了内部链接属性,使得这个全局变量只能在自己所在的源文件内部使用,其他文件不能再使用,给我们的感觉是作用域变小了。即static修饰全局变量,使全局变量失去了外部属性,作用域变小,生命周期不变(仍是整个工程),存储位置不变(在静态区)。

11.2.3.修饰函数

 若static修饰函数,我们以下面两个代码进行对比,并进行解释。

 无static修饰的代码:

有static修饰的代码:

 注:这里我们可以看出函数本身也是具有外部链接属性的。

结论:static修饰函数的时候,函数本来也是具有外部属性的,被static修饰的时候,就变成了内部链接属性。这个函数只能在自己所在的源文件内部使用,不能在其他文件内部使用。给我们的感觉是改变了作用域。


12.#define定义常量和宏

#define定义标识符常量:

#define M 100
#define STR "hehe"

int main()
{
printf("%dn",M);        //输出结果:100
printf("%sn",STR);      //输出结果:hehe
return 0;
}

#define定义宏:

#define ADD(X,Y) ((X)+(Y))
int main()
{
int a=10;
int b=20;
int ret=ADD(a,b);
printf("%dn",ret);     //输出结果:30

return 0;
}

13.指针

13.1.内存
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。 所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是 1 个字节 。 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该 内存单元的地 址 。

内存地址
一个字节0xFFFFFFFF
一个字节0xFFFFFFFE
一个字节
............
一个字节0x00000002
一个字节0x00000001
一个字节0x00000000

一、变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。 取出变量地址如下:

代码:

#include

int main()
{
	int a = 10;    //a要在内存中开辟空间
	printf("%pn", &a);
	return 0;
}

 内存调试:

 

运行结果:

012FFC48

内存占用情况:

内存地址(指针)
一个字节0xFFFFFFFF
一个字节0xFFFFFFFE
一个字节
............
a100x012FFC4B
0x012FFC4A
0x012FFC49
0x012FFC48
............
一个字节0x00000002
一个字节0x00000001
一个字节0x00000000

注:
1.这里a占四个字节,每个字节都有地址,a的地址是用四个字节中第一个字节的地址来表示(较小的地址)

2.&:取地址操作符。

3.%p:用来打印地址。

4.十六进制数是以0x开头,八进制数以0开头,内存地址是以十六进制表示的。

二、当我们想把a的地址存起来的时候,需要定义指针变量。
代码:

#include

int main()
{
	int a = 10;    //a要在内存中开辟空间
    char ch='w';
	int * p = &a;     //p就是指针变量
    char * pc=&ch;
    printf("%pn",p);
    printf("%pn",&a);   //与上一行代码打印相同都为a变量的地址

	return 0;
}

内存占用情况:

内存地址(指针)
一个字节0xFFFFFFFF
一个字节0xFFFFFFFE
一个字节
............
a100x012FFC4B
0x012FFC4A
0x012FFC49
0x012FFC48
............
p0x012FFC48
............
一个字节0x00000002
一个字节0x00000001
一个字节0x00000000

注:

1.p存储的是a的四个字节中第一个字节的地址(较小的地址),p里面存的是a的地址,那么p就有能力找到a的存储空间,所以p指向a,称p为指针变量(指针变量的第一种理解)

2.int * 中的*告诉我们p是指针变量  ,int是说明p是指向一个整型变量的。char *同理。 

3.地址是放在指针变量中的,我们把地址也称为指针,这个变量是存放地址的,也就是存放指针的,因此称为指针变量(指针变量的第二种理解)

三、指针变量的作用(指针变量解引用为指向的变量)

#include

int main()
{
	int a = 10;    
	int * p = &a;     
    *p=20;
    printf("%dn",a);       //输出为20

	return 0;
}

注:

1.*p中的*为解引用操作符或间接访问操作符,作用是通过p里面的地址找到它指向的对象,进而可以对该对象进行修改。  

2.简单的说:在此例中p是地址,*p是a变量。

13.2.指针变量的大小

在本机电脑中各类型指针变量占用空间如下代码所示:

#include
int main()
{
	printf("%d ", sizeof(char*));
	printf("%d ", sizeof(short*));
	printf("%d ", sizeof(int *));
	printf("%d ", sizeof(long*));
	printf("%d ", sizeof(long long*));
	printf("%d ", sizeof(float*));
	printf("%d ", sizeof(double *));

	return 0;
}

运行结果:

 补充:

我们现在的电脑有32位机器的,64位机器的,我们以32位机器为例子进行分析,64位机器同理。 

32位机器:32位机器有32根地址线或数据线,地址线/数据线是物理电线,使用时需要通电,通电之后有了高电平和低电平,转换成数字信号之后分别表示为1或者0。当32位地址线同时通电的时候便会产生32个数值,有以下种可能:

00000000000000000000000000000000

00000000000000000000000000000001

00000000000000000000000000000010

00000000000000000000000000000011

......

11111111111111111111111111111110

11111111111111111111111111111111

将以上32根地址线产生的32位数作为内存地址,一共可产生个这样的地址 。将32位数作为地址的编号,我们需要32个比特(bit)来存放该地址,即需要4个字节。

另外再补充:我们32位的机器,总共可以产生个地址,一个地址是一个字节的编号,那么个地址可以管理 个字节(byte)空间 ,个字节即4294967296个字节,4294967296/1024=4194304KB

4194304/1024=4096MB

4096/1024=4GB

这意味着我们32位机器可以使用和管理的内存极限就是4GB。

注:上面代码我们在编译器上选的是x86(如下图),x86编译出来是32位的,当我们选x64时,编译出来的是64位的,此时再运行,运行结果便都是8。

结论:

在32位环境下:指针大小是4个字节。

在64位环境下:指针大小是8个字。


14.结构体

14.1.结构体的类型定义及使用

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include

//结构里类型定义
struct stu
{
	char name[20];
	int age;
	char sex[10];
};

int main()
{
    //创建结构体变量,并且初始化
	struct stu zhangsan = { "张三",30,"男" };
	struct stu lisi = { "李四",24,"保密" };

    //打印结构体的数据
	printf("%s %d %sn", zhangsan.name, zhangsan.age, zhangsan.sex);
	printf("%s %d %sn", lisi.name, lisi.age, lisi.sex);

	return 0;
}

运行结果:

注:

1.数组只有定义的同时初始化了才可以用name[ ]来表示,因为此时数组的大小已经确定了,数组定义的时候不初始化则必须定义数组空间大小。此时在结构体中无法初始化,因此数组空间大小必须明确指定。

2.里面用到“.”操作符,它是结构体成员访问的操作符,其访问规则是:结构体变量.结构体成员。

3.一个英文字母占一个字节也是一个字符,一个汉字占两个字节也是两个字符。

如:‘a’占1个字符,算长度时因为没有‘/0’因此不确定。

        “a”占2个字符,算长度时为1。

       “中国”占5个字符,算长度时为4。

14.2.指针变量应用于结构体及->操作符的使用

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include
struct stu
{
	char name[20];
	int age;
	char sex[10];
};
int main()
{
	struct stu lisi = { "李四",24,"保密" };

	struct stu* pl = &lisi;     //定义指针变量pl
	printf("%s %d %sn", (*pl).name, (*pl).age, (*pl).sex);
	printf("%s %d %sn", pl->name, pl->age, pl->sex);
	return 0;
}

运行结果:

 注:->操作符也是结构体成员访问操作符,用法为:结构体指针->结构体成员。


本文只是初识c语言,把c语言的很多语法简单的过了一遍,这样可以对这些语法有一个全局的认识,后面我们会对这些语法点进行详细的讲解。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/347129.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号