C语言笔记

整理了一些C语言知识点👇

编程规范

关键字不允许作为标识符,标识符必须由字母或下划线开头,除开头外,其他位置都可以由字母下划线或数字组成。某些编译程序仅能识别前6个字符,故应该规范好标识符前6位。

数据类型——常量

整形常量:

ngNum=1000L;		//加后缀L表示长整形

UnsignLongNum=500U;	//加后缀U表示无符号整形

OctalNumber1=0123;	//加前缀0表示八进制

AlgorismNumber1=123;//十进制不需要修饰
 
HexNumber1=0x3ba4;	//加前缀0x表示十六进制(字母和后缀大小写通用) 

整形数据都以二进制方式存放于内存,其数值是以补码形式表示的,正数的补码与其原码相同,负数的补码是将该数绝对值的二进制形式按位取反后再加1。

实型(浮点型)常量:

SciNum1=123.45;				//科学计数方式:十进制的小数方法描述实型

SciNum2=5.458e-1;			//指数方式:5.458*10^(-1)

FloatNum-1.2345e2F;			//单精度类型

LongDoubleNum=5.348e-1L;	//长双精度类型 

DoubleNum=1.2345e2;			//不加后缀,默认为double双精度类型

字符型常量

字符常量
#include<stdio.h>
int main()
{						//''表示定界符
	putchar('H');		/*输出字符常量H*/
	putchar('e');		/*输出字符常量e*/
	putchar('l');		/*输出字符常量l*/
	putchar('l');		/*输出字符常量l*/
	putchar('o');		/*输出字符常量o*/
	putchar('\n');		/*进行换行*/
	return 0;
}
字符串常量

C语言中存储字符串常量时,系统会在字符串的末尾自动加一个“\0”,作为字符串的结束标志,此时字符串长度为字符数加1。一个或多个文字如也是一个字符串常量。

#include<stdio.h>					/*包含头文件*/

int main()
{									//""表示定界符
	printf("What a nice day!\n");	/*输出字符串*/
	return 0;						/*程序结束*/
}

转义字符

转义字符意义
\t横向跳到下一制表位置
\v竖向跳格
\b退格
\r回车
\f走纸换页
\\反斜杠“ \ ”
\’单引号符
\"双引号符
\n换行符
\a鸣铃
\0空字符
\ddd1~3位八进制所代表的字符
\xhh1~2位十六进制数所代表的字符

注意:在字符串中,一个转义字符(如:\ddd )占一个字符长度

符号常量

#define 标识符 常量 不带分号

数据类型——变量

32位平台下👇

类型关键字内存大小从整数最高位开始输出,输出的数位上的数字正确的数位个数(即有效数位)范围
有符号基本整型int4字节--2147483648~2147483647
无符号基本整型unsigned4字节-0~4294967295
有符号短整型short2字节--32768~32767
无符号短整型unsigned short2字节-0~65535
有符号长整型long4字节--2147483648~2147483647
无符号长整型unsigned long4字节-0~4294967295
单精度类型float4字节四字节=8位(其中最多只有6位可以用作小数点后的数字部分,没用上的被用于整数部分)-3.4E-38 ~3.4E+38
双精度类型double8字节8字节=16位(其中最多只有6位可以用作小数点后的数字部分,没用上的被用于整数部分)-1.7E-308~1.7E+308
长双精度类型long double8字节不同编译器位数不同-1.7E-308~1.7E+308
字符型char1字节--128~127
无符号字符型unsigned char1字节-0~255

想输出超出位数的数字部分需要在占位符的%后加上 “.”+数字
但是,超过位数范围的部分输出的数字会出错
不同位数平台下同一数据类型占用内存大小不都相同,编程中可以利用sizeof()计算数据类型内存大小

变量的存储类别

数字后添加字母的作用

U表示该常数用无符号整型方式存储,相当于unsigned int;
L表示该常数用长整型方式存储,相当于long
F表示该常数用浮点方式存储,相当于float
数值前面加“0”的意义是该数值是八进制。
数值前面加“0x”的意义是该数值是十六进制。
补充:数值后面加“”H“、“h”的意义是该数值是用16进制表示的。数值后面加“”B“、“b”的意义是该数值是用2进制表示的。

auto 变量

用于定义一个局部变量为自动的,局部变量所在模块执行完后系统会自动释放auto变量的存储空间,故每次执行到定义该变量时,都会产生一个新的变量并对其重新初始化,事实上,关键字auto是可以省略的,如果无特别指定,局部变量的存储方式默认为自动的。

#include<stdio.h>
void AddOne()
{
	auto int iInt=1;				/*定义整型变量*/
	iInt=iInt+1;					/*变量加1*/
	printf("%d\n",iInt);			/*显示结果*/
}
int main()
{
	printf("第一次调用:");			/*显示结果*/
	AddOne();						/*调用Show函数*/
	printf("第二次调用:");			/*显示结果*/
	AddOne();						/*调用Show函数*/
	return 0;						/*程序结束*/
}

在这里插入图片描述

static 变量

static 变量为静态变量,可用于声明内部变量或外部变量,其初始化操作只在第一次执行时起作用,在随后的运行过程中其值为上一次该变量被操作后存储下来的值。由于定义在函数内部且其值可变,故相比全局变量更加“安全”

#include<stdio.h>
void AddOne()
{
	static int iInt=1;				/*定义整型变量*/
	iInt=iInt+1;					/*变量加1*/
	printf("%d\n",iInt);			/*显示结果*/
}
int main()
{
	printf("第一次调用:");			/*显示结果*/
	AddOne();						/*调用Show函数*/
	printf("第二次调用:");			/*显示结果*/
	AddOne();						/*调用Show函数*/
	return 0;						/*程序结束*/
}

在这里插入图片描述

register变量

寄存器存储类变量,存放在寄存器而非内存的局部变量,好处是可以提高程序的运行速度。实际上,只有早期的编译器会执行此修饰符,如今的编译器能比程序员做出更好的决定,所以很多C语言编译器会忽略register对变量的修饰。
如果想有效地利用寄存器register关键字,必须像汇编语言程序员那样了解处理器的内部结构,知道可用于存放变量的寄存器的数量,种类以及工作方式。但是,不同计算机对于这些细节可能是不同的,因此,对于一个具备可移植性的程序来说,registerd的作用并不大。

运算符与表达式

自动类型转换

自动类型转换原则
字段类型
下面几种情况都发生自动类型转换:

1、算术运算式中,低类型能够转换为高类型。
2、赋值表达式中,右边表达式的值自动隐式转换为左边变量的类型,并赋值给他,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型比左边长时,将丢失一部分数据,丢失的部分按四舍五入向前舍入。
3、函数调用中参数传递时,系统隐式地将实参转换为形参的类型后,赋给形参
4、函数有返回值时,系统会隐式地将返回值的类型转换为返回值类型,赋值给调用函数。
5、在程序中将数据用printf函数以指定格式输出时,当要输出的盐据类型与输出格式不符时,便自动进行类型转换
注意:较长型数据转换成短型数据输出时,其值不能超出短型数据允许的值范围,否则转换时将出错。如:

 long a=80000;
 printf("%d",a);

运行结果为14464,因为int型允许的最大值为32767,80000超出此值,故结果取以32768为模的余数,即进行如下取余运算:
(80000-32768)-32768=14464;

6、所有浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也会先转换成double型,再作运算。

强制类型转换

float i=10.1f;
int j=(int)i;

在变量前使用包含要转换类型的括号,就对变量进行了强制类型转换
注意:高级别向低级别转换可能会出现数据的丢失,在使用强制类型转换时要注意

算术运算

笔记:两个int型相除的结果为int型,7/4的结果为1,舍去了小数部分,如果其中一个数为负数,会采取“向零取整”的方法,即向0靠拢取整,结果为-1。

自增/自减运算符:放在变量前面,那么变量在参加表达式运算之前完成自增或自减运算,放在变量后面,则自增或自减运算在变量参加了表达式运算之后完成

算术运算符的结合性:当算术运算符的优先级相同时,结合方向为“自左向右”。

关系运算

关系运算符用于对两个表达式的值进行比较,返回一个真值 1 或假值 0

逻辑运算

C语言中,表达式的值非零,那么其值为真。非零的值用于逻辑运算,则等价于1;假值总是为0。

符 号功 能
&&逻辑与
丨丨逻辑或
单目逻辑非

位运算

符 号名 称功 能
&“与”运算符使参与运算的两数对应的二进位相“与”,对应的两个二进位均为1则结果为1,否则为0(双目)
“或”运算符使参与运算的两数各对应的二进制位相“或”,只要对应的两个二进位有一个为1,结果位就为1(双目)
^“异或”运算符使参与运算的两数各对应的二进位相“异或”,当对应的两个二进位数相异时结果为1,相同时为0(双目)
~“取反”运算符对参与运算的各二进位按位求反,将0变成1,1变成0(单目,右结合性

&
清零操作:要将原数中为1的位置为0,只需使与其进行“与”操作的数所对应的位置为0便可实现清零操作。
取特定位:取后n位,则要与后n位均是1的数相“与”

|
归一操作:要将某几位为1,只需与几位是1的数执行“或”操作便可

^
用于简单的加密算法
要将后n位翻转,只需与后n位都是1的数进行“异或”操作即可
不使用临时变量的情况下实现两个变量值的互换。↓↓↓

x=x^y;
y=y^x;
x=x^y;

~
取反操作(单目)

移位运算

<<
“左移”运算符(双目),把“<<”左边的运算数的各二进位全部左移若干位,“<<”右边为移动的位数,高位丢弃,低位补0
如a<<2,假设 a=39,那么 a 在内存中的存储情况如下↓↓↓

|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0 |0|0|1|0|0|1|1|1| 移位前
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0 |1|0|0|1|1|1|0|0| 移位后

>>
“右移”运算符(双目),把“>>”左边的运算数的各二进位全部右移若干位,“>>”右边为移动的位数,在进行右移时,当为正数时,最高位补0;而为负数时,最高位补0还是补1取决于编译系统的规定。移入0的称为“逻辑右移”,移入1的称为“算术右移”。

注意:当移动的位数超过类型的长度时,会取余数,然后移动余数个位
对于10进制数字,左移一位在末尾加上一个0,数值变大10倍。同理,对于二进制数字,左移一位是在末尾加上一个0,数值变为原来的2倍,在左移运算中前提是移出位不含1,利用左移运算做数据*2的循环运算效率更高。
>>>
逻辑右移也叫无符号右移,运算规则:低位溢出,高位补0

循环移位

循环移位就是将移出的低位放到该数的高位,或者将移出的高位放到该数的低位

循环左移
请添加图片描述

z=x>>(32-n);	//将x的左端n位先放到z中的低n位中
y=x<<n;			//将x左移n位,其右边低n位补0
y=y|z;			//将y与z进行按位“或”运算

循环右移

z=x<<(32-n);	//将x的右端n位先放到z中的高n位中
y=x>>n;			//将x右移n位,其左端高n位补0
y=y|z;			//将y与z进行按位“或”运算

推荐热文:【技巧总结】位运算装逼指南

位段

逗号运算与逗号表达式

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

逗号表达式的求解过程:先求解表达式1,再求解表达式2,一直求解到表达式n。整个逗号表达式的值是表达式n的值。

Value,1+25+7

上面的语句中,Value所得到的值为7而非12,因为赋值运算符的优先级比逗号运算符的优先级高

Value=(2+5,1+2,5+7);

使用括号后,Value的值为12

复合赋值运算符

+= -= *= /=
a=a+1中,表达式a计算2次,对于a+=1,表达式仅计算1次,一般来说,这种区别对于程序的运行没有太大的影响,但是如果表达式中存在某个函数的返回值,那么函数将被调用两次。

运算符优先级和结合性表格

优 先 级运 算 符含 义结 合 性
1( )圆括号自左向右
[ ]下标运算符
->指向结构体成员运算符
.结构体成员运算符
2!逻辑非运算符(单目)自右向左
~按位取反运算符(单目)
++、--自增,自减运算符(单目)
-负号运算符(单目)
*指针运算符(单目)
&地址与运算符(单目)
sizeof长度运算符(单目)
(类型)强制类型转换(数据类型)表达式
3*、/、%乘法、除法、求余运算符自左向右
4+、-加法、减法运算符
5<<、>>左移、右移运算符
6<、<=、>、>=小于、大于或等于、大于、大于或等于运算符
7==、!=等于、不等于运算符
8&按位与运算符
9^按位异或运算符
10|按位或运算符
11&&逻辑与运算符
12||逻辑或运算符
13?:条件运算符(三目)自左向右
14=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|=赋值运算符
15,逗号运算符(顺序求值运算符)自左向右

常用的数据输入/输出函数

字符

输出:putchar函数

putchar('A');
putchar('\101');//反斜杠和八进制数字构成八进制转义字符,'A'的ASCII码的八进制值为101
putchar(\n);

更多关于转义字符推荐文章:C语言中的转义字符

输入:getchar函数

int cChar=getchar();//字符可以赋給一个字符变量或整型变量
char cChar=getchar();

字符串

输出 语法格式:int puts(char *str);

puts("I LOVE CHINA!");

注意:puts函数会在字符串中判断“\0”结束符,遇到结束符时,后面的字符不再输出,并且自动换行。

输入 语法格式:char *gets(char *str);
作用是将读取的字符串保存在形式参数str变量中,读取过程直到出现新的一行为止,其中新一行的换行字符将会转换为空终止符“/0”。

注意:在输入字符或者字符串数据时以回车结束,当输入完数据后,要使用getchar函数接受回车符,否则下次使用getcharha函数时将得到回车符。

printf

printf(格式控制,输出列表)

格式字符用于输出👇
d,i带符号十进制整数
o无符号八进制整数
x,X无符号十六进制整数。x:a~f小写输出;X:大写输出
u无符号十进制整数
c字符,只输出一个字符
s字符串
f小数形式
e,E实数的指数形式。e:指数用“e”表示;E:指数用"E"表示
g,G判断并输出“%f” "%e"格式中宽度较短的一种形式,不输出无意义的0,若以指数形式输出,则指数以大写表示

附加格式说明字符
关于字符串:
“%10s”:“%ms”表示输出字符串占m列,如果字符串长度大于m,则突破限制将其全部输出,如果小于m,则用空格向左补齐;“%-ms”中负号表示右补空格
“%10.3s”: “%m.ns”表示输出占m列,但只取字符串左端n个字符且这n个字符出现在m列的右侧,左补空格;“%-m.s”中负号表示n个字符输出在m列内的左侧,右补空格,如果n大于m,则m自动取n值保证输出n个字符
在格式控制处使用“%%”可以输出“%”符号

控制小数位数推荐文章:
c语言控制输出格式-小数点位数

scanf

scanf(格式控制,地址列表)

格式字符用于输入👇
d,i有符号十进制整数
u无符号十进制整数
o无符号八进制整数
x,X无符号十六进制整数
c单个字符
s字符串
f实型,可以是小数形式也可以是指数形式
e,E,g,G与f作用相同(e,g大小写作用相同)
附加格式功能说明
l用于输入长整型数据:%ld %lo %lx %lu 和double型的数据:%lf %le
h用于输入短整型数据:%hd %ho %hx
n(整数)%nd 指定输入数据所占的宽度
**%d 表示指定的输入项在读入后不赋給相应的变量

选择结构

if

嵌套
在使用if语句嵌套时,应注意if与else的配对情况,else总是与其上面的最近的未配对的if进行配对

条件运算符
格式: 表达式1?表达式2:表达式3
检验表达式1的值,为真则返回表达式2的结果值,为假则返回表达式3的结果值

if(a>b)
	{max=a;}
else
	{max=b;}

改写👇

max=(a>b)?a:b

switch

switch(表达式)
{
	case 情况1:
		语句块1;
	case 情况2:
		语句块2;
	...
	case 情况n:
		语句块n;
	default:
		默认情况语句块;
}

switch语句检验的表达式必须为整形,可以包含运算符和函数调用
case语句检验的值必须为整型常量,可以是常量表达式或常量运算
每个switch结构只能有一个default语句,而且default语句可以省略

在使用switch语句时,每一个case情况中都要使用break语句,break使得执行完case语句后跳出switch,如果case匹配成功了,但缺少break,程序还会继续向下执行 (default也会被执行),直到遇到break,return和swith结束为止

switch()
{
case 1:
		表达式;
		break;
/*多路开关模式*/
case 2:
case 3:
case 4:
	表达式;
	break;
case 5:
	表达式;
	break;
default:
	表达式;
	break;

循环控制

while 和 do…while

while(表达式)
{
	语句1;
	...

首先检验表达式,为假则退出while循环,为真则执行语句(块)后回到while处重新检验表达式,循环中有假才跳出循环

do
{
	语句1;
	...while(表达式);

首先执行一次循环体语句,然后判断表达式,为真返回重新执行循环体语句,执行循环直到表达式的判断为假才结束循环

for

for(表达式1;表达式2;表达式3) 语句块
在这里插入图片描述
表达式1,2,3都可以省略,但是表达式之间的分号不能省略;表达式1和3可以使用逗号表达式

转移语句

goto

goto 标识符;
使程序立即跳转到函数内部的任意一条可执行语句,标识符是同一个函数内某条语句的标号,标号可以出现在任何可执行语句的前面,并且以一个“:”作为后缀

goto Show;
printf("the message before ShowMessage");
Show:
	printf("ShowMessage");
	//第一个printf不会被执行,第二个printf会执行

break

终止并跳出循环,继续执行后面的代码,只能用于循环语句或switch语句

continue

程序返回到循环头部继续执行,而不是跳出循环,continue语句只结束本次循环,而不是像break那样终止整个循环

for1.初始化;2.条件判断;3.变量迭代)
{
	if(4.某条件)
	{
		continue5.其他语句;
	}
}

执行步骤为
1 ----> 2 ----> 4条件满足 ----> ==5.后面的其他语句不执行,直接执行3迭代变量,然后进入下一轮循环条件判断2 ==----> 再判断4 ----> …

数组

常见数组

一维数组初始化:

#include<string.h>
memset(数组名,0,sizeof(数组名));

二维数组:
行下标可省,列下标不可省,系统可以根据后面的下标和元素个数确定第一个下标,正确写法👇

int iArray[][3]={1,2,3,4,5,6};

系统会根据数据的个数进行分配,共有6个数据,数组每行分为3列,当然可以确定数组为2行
也可以分行给数组元素赋值(不管是行下标还是列下标,其索引都是从0开始的)👇

int iArray[2][3]={{1,2,3},{4,5,6}};

多维数组的元素地址连续
字符数组:

char cArray[]={'H','e','l','l','o'};
char cArray[]={"Hello"};
char cArray[]="Hello";
输出字符数组:printf("%s",cArray);

当字符数组以单个字符进行赋值时,记得在数组的最后要加上‘\0’;

字符串处理函数

字符串复制

#include<string.h>
strcpy(目的字符数组名,源字符数组名);

把源字符数组中的字符串复制到目的字符数组中,字符串结束标志“\0”也一同复制;源字符数组名可以是一个字符串常量

字符串连接

#include<string.h>
strcat(目的字符数组名,源字符数组名);

把源字符数组中的字符串连接到目的字符数组中字符串的后面,并删去目的字符数组中原有的结束标志“\0”,目的字符数组应有足够长度用于连接字符串

字符串比较

#include<string.h>
strcmp(字符数组名1,字符数组名2);

将一个字符串与另一个字符串从首字母开始,按照ASCII码的顺序逐个进行比较:
字符串1=字符串2,返回值为0
字符串1>字符串2,返回值为正数
字符串1<字符串2,返回值为负数

字符串大小写转换

#include<string.h>
strupr(字符串);

将字符串中的小写字母转换成大写字母,其他字母不变

#include<string.h>
strlwr(字符串);

将字符串中的大写字母转换成小写字母,其他字母不变

获得字符串长度

#include<string.h>
strlen(字符数组名);

计算字符串的实际长度(不含字符串结束标志“\0”),函数返回值为字符串的实际长度

数组应用:反转输出字符串

#include <stdio.h>
int main()
{
	int i;
	char String[7]  = {"mrsoft"};
	char Reverse[7] = {0};
	int size;
	size = sizeof(String);	/*计算源字符串长度*/

	/*循环读取字符*/
	for(i=0;i<6;i++)
	{
		Reverse[size-i-2] = String[i];	/*向目标字符串中插入字符*/
	}

	/*输出源字符串*/
	printf("输出源字符串:%s\n",String);
	/*输出目标字符串*/
	printf("输出目标字符串:%s\n",Reverse);

	return 0;						/*程序结束*/
}

函数

参数

参数列表中存在多个同类型参数时,不可用类型定义+逗号,必须一一定义。
数组用作函数参数:用数组名作为实参,指向该数组的第一个元素的指针就被传递到函数中
被调用的函数的参数可以为可变长度数组或指针

void Function(iInt iArray[]);//参数为可变长度数组

int iArray[10];
Function(iArray);
void Function(int* pPoint);//参数为指针

int iArray[10];
Function(iArray);

函数调用

函数在表达式中被调用

iResult = iNum3 * AddTowNum(3,5);   //在表达式用调用AddTwoNum函数

函数在参数中被调用

iResult = AddTwoNum(10,AddTwoNum(3,5));  //函数在参数中

函数嵌套调用:略

递归调用

#include<stdio.h>
void DisplayNames(char** cNameArray);	/*声明函数*/

char* cNames[]=		/*定义全局字符串数组*/
{
	"Aaron",		/*为字符串进行赋值*/
	"Jim",
	"Charles",
	"Sam",
	"Ken",
	"end"			/*设定结束标志*/
};

int main()
{
	DisplayNames(cNames);		/*调用递归函数*/
	return 0;
}

void DisplayNames(char** cNameArray)
{
	if(*cNameArray=="end")	/*判断结束标志*/
	{
		return ;			/*函数结束返回*/
	}
	else
	{
		DisplayNames(cNameArray+1);		/*调用递归函数*/
		printf("%s\n",*cNameArray);		/*输出字符串*/
	}
}

内部函数

static 返回值类型 函数名(参数列表);

内部函数只能在所在的源文件中使用,即使不同的源文件中有相同的函数名也没有关系

外部函数

extern 返回值类型 函数名(参数列表);

== C语言中定义函数时,如果不指明函数是内部还是外部,默认指定该函数为外部函数 ==

函数应用

#include<stdio.h>
#include<math.h>	//包含头文件
int num1,num2;
long num3,num4;
float num5,num6;
double num7;num8;
num1=abs(num2);		//求整数的绝对值
num3=labs(num4);	//求长整形的绝对值
num5=fabs(num6);	//求浮点数的绝对值
num7=sin(num8);		//求解正弦
num7=cos(num8);		//求解余弦
num7=tan(num8);		//求解正切
#include<stdio.h>
#include<ctype.h>	//包含头文件
char c; 
isalpha(c);		//检测字母(大写或小写),是则返回非零值,否则返回0
isdigit(c);		//检测数字,是则返回非零值,否则返回0
isalnum(c);		//检测字母或数字,是则返回非零值,否则返回0

指针

" & " 和 “ * ”的运算符优先级别相同,按自右向左的方向结合

类型 * 变量名;	//类型说明表示本指针变量所指向的变量的数据类型
printf("%p",p);		//输出指针地址
p++;				//不是给地址加1,而是使指针指向下一个存放该类型变量的地址

int *p,a[10],i;		
p=a;				//数组的名称就是数组在内存中的首地址,可以赋值給指针变量,也可以用	p=&a[0];
printf("%d %d",*(p+i),*(a+i));//可用*(p+i),*(a+i)表示数组元素

int (*p)[5];		//定义指针p,指向一个整型的一维数组

返回指针值的函数

类型名 *函数名(参数列表);

通过指针引用二维数组:

*(a[0]+n)		//表示第0行第n个元素
*(*(a+n)+m)		//表示第n行第m列的元素
*(a[n]+m)		//表示第n行第m列元素

一维指针数组

#include<stdio.h>
main()
{
	int i;
	char *month[]=
	{
               "January", 
               "February", 
               "March", 
               "......"
	};								/*给指针数组中的元素赋初值*/
	for(i=0;i<12;i++)
		printf("%s\n",month[i]); 	/*输出指针数组中的各元素*/
}

指向指针的指针

类型 **指针变量名;	//p指向另一个指针变量,该指针变量又指向一个变量,*运算符自右向左结合 

指针数组作main函数的参数

main(int argc,char *argv[])
参数argc是命令行输入参数的个数,argv[]的大小参数决定,数组内存放了所有的命令行参数,利用该指针数组作main函数的形参,可以向程序传送命令行参数,C的源程序经过编译、链接后会生成扩展名为.mp4的可执行文件,该文件可以在操作系统下直接运行

输出main函数的参数内容:

#include<stdio.h>
main(int argc,char *argv[])								/*main函数为带参函数*/
{
	printf("the list of parameter:\n");
	printf("命令名:\n");
    printf("%s\n",*argv);
	printf("参数个数:\n");
	printf("%d\n",argc);
	
}

指针变量加(类似数组的)下标

指针变量加上下标,代表的意义就是:指针中的值就是起始地址,下标则是从指针中存储的地址作为起始地址开始偏移的,实际就是一个数组元素
注意:对同一非空指针delete多次,只有第一次delete被正确执行,之后的delete全部发生异常。

结构体

结构体类型和结构体变量

struct 结构体名	//结构体类型的定义
{
	成员列表
};				//不要忘记分号
struct 结构体类型名 结构体变量名;	

以上可简写为👇

struct 结构体名	//结构体名可省略
{	
	成员列表;
}变量名列表;		//可以定义多个变量

结构体数组

struct 结构体名	
{
	成员列表;
}数组名;

struct 结构体名	
{	
	成员列表;
}
struct 结构体类型名 数组;	

初始化操作

结构体变量

struct date
{
	int year;
	int month;
	int day;
};
struct Student 
{
	char nName[20];
	char cSex;
	int iGrade;
	struct date brithday;
}student1={"HanXue","W",3,{1986,12,6}};		//定义变量并初始化,数据顺序与结构体的成员列表顺序一致
				//程序中在为包含结构体变量的结构体变量初始化时要注意,使用大括号将赋值的数据包含在内

结构体数组

struct 结构体名
{
	成员列表;
}数组名={初始值列表};			//每个数组元素内的数据要与结构体成员列表的顺序一致
								//定义结构体数组时,可以不指定数组元素个数
								//编译器会根据后面的初始值列表判断数组的元素个数

结构体指针

结构体类型 *指针名;

引用结构成员时,*pStruct一定要使用括号,因为点运算符的优先级是最高的 → (*pStruct).变量名

指向结构体数组的结构体指针

struct Student* pStruct;
pStruct=student;		//student表示数组的第一个元素的地址,所以指针指向数组的首地址

一般用指向结构体变量的指针作为函数参数,如果直接传递结构体变量或结构体变量的成员,形参也要占用内存,增加了时间和空间开销,且实参不会因形参改变而改变

浅谈堆与栈

堆用来存放动态分配内存空间,而栈用来存放局部数据对象、函数的参数

#ifdef及#ifndef命令

#ifdef 宏替换名
语句段
#endif	//endif命令用来表示#if段的结束

含义:如果宏替换名已被定义过,则对“语句段”进行编译,否则不编译
#ifdef 可与#else 连用👇

#ifdef 宏替换名
语句段1
#else
语句段2
#endif

#ifndef 与#ifdef 相反👇

#ifdef 宏替换名
语句段
#endif

含义:如果宏替换名没有被定义过,则对“语句段”进行编译,否则编译
#undef 宏替换名
含义:#undef命令可以删除实现定义好的宏定义

#define MAX_SIZE 100
char array[MAX_SIZE];
#undef MAX_SIZE		//直到遇到#undef语句之前的语句都编译
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值