初识C语言

1. 初识C语言

C语言是一门通用计算机编程语言,广泛应用于底层开发。
C语言是一门面向过程的计算机编程语言,它与C++,Java等面向对象的编程语言有所不同。

第一个C语言程序:

#include<stdio.h>

int main(void)
{
	printf("hello world!\n");
	return 0;
}

注释:
stdio:标准输入输出
main函数:main函数是主函数,也是程序的入口,并且有且仅有一个
main(void):加参数void表示main函数不需要参数
printf函数:它是一个库函数,主要用于在屏幕上打印相关的数据,使用库函数就得包含对应的头文件

//一种旧式写法,在一些老式的编译器中可以使用
void main()
{
...
}

2.数据类型

类型的存在主要是为创建变量服务的,常用的数据类型如下:
字符类型:char
整数类型:short int long longlong
浮点类型:float double

int main()
{
	printf("%d\n",100);//100
	printf("%d\n",sizeof(char));//1
	printf("%d\n",sizeof(short));//2
	printf("%d\n",sizeof(int));//4
	printf("%d\n",sizeof(long));//4
	printf("%d\n",sizeof(long long));//8
	printf("%d\n",sizeof(float));//4
	printf("%d\n",sizeof(double));//8

	return 0;
}

注释:
%d:用于打印整数
sizeof():是一个操作符,用来计算类型和变量的大小

计算机的基本单位
bit:比特位,存一个二进制位1或者0
byte:字节,1byte=8bit
KB:1KB=1024byte
MB:1MB=1024KB
GB:1GB=1024MB
C语言标准规定:sizeof(long)>=sizeof(int) ,但是long的大小不一定要是8只要是比4的数字即可

C语言有没有字符串类型?
C语言没有原生字符串类型。像Java有自己的字符串类型string,而在C语言中,字符串则往往是被当做字符数组或者字符指针来进行处理的。在C语言中,字符串有3个核心要点:第一是用指针指向字符串的头;第二是固定尾部(字符串总是以\n来结尾);第三是组成字符串的各字符彼此地址相连。

3.常量与变量

常量
常量:用来描述变化的数据

定义变量:

int age=150;
float weight=55.5f(加f表面是个float的类型);
char ch='w';

变量的分类:
局部变量:在大括号内定义的变量
全局变量:在大括号外定义的变量

int a=100;//全局变量

void test()
{
int c=1000;//局部变量
}
int main()
{
	//运行时会报错,因为a是局部变量,只能在括号以内使用
	{
		int a = 10;//局部变量
	}
	printf("%d\n",a);

	//可以运行,不会发生错误
	int a = 10;//局部变量
	printf("%d\n", a);

	return 0;
}

局部变量优先原则:
当局部变量和全局变量同名时,局部变量优先使用

int a = 100;
int main()
{
	int a = 10;//局部优先原则
	printf("a=%d\n",a);//输出结果为10
	return 0;
}

变量的使用:

//求两数之和
int main()
{
	int num1 = 0;
	int num2 = 0;
	int sum = 0;

	//输入
	scanf("%d %d",&num1,&num2);
	//求和
	sum = num1 + num2;

	//输出
	printf("sum=%d\n",sum);
	printf("%d %d\n",num1,num2);

	return 0;
}

注释:
scanf():输入函数
printf():输出函数
%s:输出字符串
%d:输出整数

scanf()函数为什么不安全?如何解决?
因为scanf() 函数不会对存放数据的内存空间进行检测,在使用的过程中输入的数据可能会大于原本分配的内存空间,进而导致溢出,造成越界访问,所以scanf()函数不安全。
解决办法:
法1:在源文件开头定义:#define _CRT_SECURE_NO_WARNINGS 1(比较麻烦,每次新建工程都要重新定义,建议采用方法2)
法2:在VS的安装路径下搜索到newc++file.cpp这个文件,复制一份到桌面,并在文件中加入#define _CRT_SECURE_NO_WARNINGS 1并保存,然后以管理员的身份替换到原来的文件即可
法:3:通过项目 -> 属性 -> C/C++ -> 预处理器 -> 预处理器定义 -> 编辑,在框内写入 _CRT_SECURE_NO_WARNINGS
法4:在源文件开头加入一行命令:#pragma warning(disable:4996)

变量的作用域和生命周期
作用域:通常来说,一段程序中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域
局部变量:局部变量的作用域就是局部变量所在的局部范围
全局变量:全局变量的作用域是整个工程

//局部变量:局部变量的作用域就是局部变量所在的局部范围
int main()
{
	{
		int a = 10;//a只能在括号内使用,超出这个范围就不能使用
	}
	printf("%d\n",a);//运行时会发生报错,因为a超出所在范围
}

//全局变量:全局变量的作用域是整个工程
int a = 10;
void test()
{
	printf("test:%d\n",a);
}
int main()
{
	test();
	printf("main:%d\n",a);
	return 0;
}

//在另一个文件中定义的全局变量,需要声明外部符号:extern
extern int g_val;
int main()
{
	printf("%d\n",g_val);
	return 0;
}

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

常量:
常量:用来描述不变的数据

常量的类型:
字面常量
const修饰的常变量
#define定义的标识符常量
枚举常量

字面常量`

int a = 100;
char ch = 'c';

const修饰的常变量

//这里的n属于变量其值是可以修改的
int n = 10;//n为变量
printf("n=%d\n",n);//10
n = 20;//n为变量
printf("n=%d\n",n);//20
//这里的n属于常变量其值是不可以修改的
const int n = 10;//常变量
printf("n=%d\n",n);
n = 20;//运行时会报错,n的值不能修改
printf("n=%d\n",n);
int arr[10] = {0};//C99标准之前的语法

int n = 10;
int arr[n] = {0};//运行不通过,因为n是个变量,中括号里面的值必须是个常量,但是在C99标准中增加一个变长数组的概念,这里指定数组大小的时候,可以使用变量了

const int n = 10;
int arr[n] = {0};//运行不通过,虽然n具有常属性,但本质上仍是个变量

#define定义的标识符常量

#define MAX 100

MAX = 101;//MAX是个标识符常量,其值不能进行修改
int m = MAX;
printf("%d\n",m);//100
printf("%d\n",MAX);//100

枚举常量

enum Sex
{
	male,
	female,
	secret
};

//枚举是C语言提供的一种自定义类型的方法
male = 10;//male是常量,其值不能修改
printf("%d\n",male);//0
printf("%d\n",female);//1
printf("%d\n",secret);//2

enum Sex s = male;//常规用法

4.字符串+转义字符+注释

字符串:
字符串:由双引号引起来的一串字符称为字符串
字符串的结束标志是一个名为\0的转义字符,在计算字符串长度的时候\0是结束标志,不算作字符串内容
%s:打印字符串

int main()
{
	char arr1[] = "abcdef";//结尾处包含一个结束标志\0
	char arr2[] = {'a','b','c','d','e','f'};//结尾处不包含结束标志\0
	char arr3[] = {'a','b','c','d','e','f','\0'};//结尾处自行添加一个结束标志\0
	char arr4[] = "abc\0def";
	printf("%s\n",arr1);//输出结果为abcdef
	printf("%s\n",arr2);//输出结果为abcdef烫烫烫烫烫abcdef,因为不包含字符串的结束标志\0
	printf("%s\n",arr3);//输出结果为abcdef
	printf("%s\n",arr4);//输出结果为abc
	return 0;
}

转义字符:
转义字符:转义也就是转变它的意思

int main()
{
    //\?:在书写连续多个问号时使用,防止他们被解析成三字母词,三字母词??)->]
	printf("(are you ok??)");//原本应该输出(are you ok],但最后的运行结果还是输出(are you ok??),编译器无法演示
	printf("(are you ok\?\?)\n");//输出(are you ok??),常规用法


    //\':用于表示字符常量
    //\":用于表示一个字符串内部的双引号
    //%c:用于打印字符
	printf("%c\n",'a');//输出结果为a
	printf("%c\n",'\'');//输出结果为'
	printf("%s\n","abc");//输出结果为abc
	printf("%s\n","a");//输出结果为a
	printf("%s\n","\"");//输出结果为"

	//\\:用于表示一个反斜杠,防止它被解释为一个转义序列
	//printf("c:\\code\\test.c\n");

	//\ddd:ddd表示1-3个八进制的数字,如\130对应X
	//\xdd:x表示十六机制,dd表示2个十六进制数字,如\x30对应0
	printf("%c\n",'\130');//八进制表示的130转化为十进制为:64+24+0=88,而88对应的ASCII值为字符X
	printf("%c\n",'\x30');

	int len = 0;
	len = strlen("abcdef");
	printf("%d\n",len);//结果为6,不计入字符串的结束标志\0

	printf("c:\test\628\test.c\n");
	printf("%d\n",strlen("c:\test\628\test.c"));//14,十四个字符分别为 c : \t e s t \62(\062) 8 \t e s t . c 
	//可能有人会问,为什么不是\628,而是\62呢?原因:\ddd中的ddd代表的是八进制数,八进制数中没有8这个数,所以很显然\62 相当于\062
	
	char arr1[] = "abcdef";
	char arr2[] = {'a','b','c','d','e','f'};
	char arr3[] = { 'a','b','c','d','e','f','\0'};

	printf("%d\n",strlen(arr1));//6
	printf("%d\n",strlen(arr2));//22 因为不包含字符串零终止符,所以22是个随机值
	printf("%d\n",strlen(arr3));//6

	return 0;
}

注释:
C语言风格的注释:/xxxxxx/,缺点:不能嵌套注释
C++风格的注释://xxxxxx,优点:可以注释一行也可以注释多行

5.选择语句

int main()
{
	int input = 0;
	printf("你要好好学习吗(1/0)?:");
	scanf("%d",&input);
	if (input == 1)
	{
		printf("好offer!");
	}
	else
	{
		printf("卖红薯!");
	}
	return 0;
}

6.循环语句

int main()
{
	int line = 0;

	while (line<20)
	{
		line++;
		printf("我要继续努力敲代码:%d\n",line);
	}
	if (line >= 20)
	{
		printf("迎娶白富美!\n");
	}
}

7.函数

函数的特点:简化代码,代码复用

int Add(a, b)
{
	int sum = 0;
	sum = a + b;
	return sum;
}

int main()
{
	int n1 = 0;
	int n2 = 0;
	int sum = 0;
	
	//输入
	scanf("%d %d", &n1, &n2);
	//计算求和
	sum = n1 + n2;
	sum = Add(n1, n2);
	//输出
  printf("sum=%d\n", sum);
}

8.数组

数组:一组相同类型元素的集合
C语言规定:数组的每个元素都有一个下标,下标是从0开始的
数组可以通过下标来访问

int main()
{
	int arr[10] = {10,11,12,13,14,15,16,17,18,19};
	printf("%d\n",arr[5]);//15

	int i = 0;
	//输入
	while (i < 10)
	{
		scanf("%d",&arr[i]);
		i++;
	}

	i = 0;
	//输出
	while (i < 10)
	{
		printf("%d ",arr[i]);
		i++;
	}

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

	return 0;
}

9.操作符

算数操作符:+ - * / %
flaot:打印输出用%f
double:打印输出用%lf

int main()
{
	int c = 10 / 3;
    printf("%d\n",c);//3

	float c = 10 / 3;
	printf("%f\n",c);//3.000000

    //想要得到3.333333,10和3两个操作数必须含有一个小数或者两个都带小数,如10.0,3.0等
	float c = 10.0/ 3;
	printf("%f\n", c);
    float d = 10/3.0;
	printf("%f\n", d);
    float e = 10.0/ 3.0;
    printf("%f\n", e);

	//%:取模,两边的操作数必须都是整数
	int a = 10 % 3;
	printf("%d\n",a);//1

	//移位操作符:>> << 移动的是二进制位,必须把十进制数字转化为二进制演示
	
	//位操作符:& ^ | 操作的是二进制位

	//赋值操作符
	int a = 10;//初始化
	a = 20;//赋值

	return 0;
}

‘0’:字符0,对应的ascii码值为48
‘\0’:转义字符,对应的ascii码值为0
0:数字0,就是0,当需要’\0’的地方,放上0也是没问题的
EOF:END OF FILE,文件结束标志,本质是-1,是文件结束标志

一个全局变量未被初始化时,默认会被初始化为0;
一个局部变量未被初始化时,默认会被初始化为随机值;

int a;//一个全局变量未初始化时,默认会被初始化为0
int main()
{
	//一个局部变量未初始化时,默认是随机值
	int b;
	printf("%d\n",b);

	printf("%d\n",a);
	char ch[10] = "hello bit";//h e l l o '' b i t '\0' 
	return 0;
}

多组输入:
scanf()返回值:scanf()返回值为读取到的输入值的个数,可以用EOF文件结束标志来判断
案例一:

//多组输入
//scanf()返回值:scanf返回值为读取到的输入值的个数,可以用EOF文件结束标志来判断
int main()
{
	int iq = 0;
	//输入
	while (scanf("%d", &iq)==1)//scanf如果读到一个有效数据,则进入循环,或者写成while(scanf("%d", &iq)!=EOF)
	{
		//输出
		if (iq >= 140)
		{
			printf("Genius\n");
		}
	}
	return 0;
}

运行结果如下:
运行结果案例二:

int main()
{
	int iq = 0;
	int q = 0;
	//输入
	while (scanf("%d %d", &iq,&q)==2)//scanf如果读到两个有效数据,则进入循环,或者写成while(scanf("%d %d", &iq,&q)!=EOF)
	{
		//输出
		if (iq >= 140&&q>=140)
		{
			printf("Genius\n");
		}
	}
	return 0;
}

运行结果如下:
运行结果单目操作符:

int main()
{
	//逻辑反操作!,在C语言中,0就是假,非0就是真
	int a = 10;
	int b = !a;//a为10为真,逻辑反操作即为假0
	printf("b=%d\n", b);//结果为0

	int a = 0;
	int b = !a;
	printf("b=%d\n",b);//结果为1

	int flag = 5;
	//如果flag为真做什么事情
	if (flag)
	{
		printf("hehe!\n");//输出hehe!
	}

	int flag1 = 0;
	//如果flag1为假做什么事情
	if (flag1)
	{
		printf("haha\n");//什么也不输出
	}


	//sizeof:计算操作数的类型长度,以字节为单位
	int a = 10;
	printf("%d\n",sizeof(a));//4
	printf("%d\n",sizeof(int));//4


	//~:对一个数的二进制按位取反


	//++,--
	int a = 10;
	int b = ++a;//前置++,先++,后使用,即先对a+1=11,再将a=11的值赋给b
	printf("a=%d b=%d",a,b);//11,11

	int a = 10;
	int b = a++;//后置++,先使用,后++,即先将a=10赋值给b,再将a+1=11
	printf("a=%d b=%d", a, b);//11,10

	int a = 10;
	int b = --a;//前置--,先--,后使用,即先对a-1=9,再将a=9的值赋给b
	printf("a=%d b=%d", a, b);//9,9

	int a = 10;
	int b = a--;//后置--,先使用,后--,即先将a=10赋值给b,再将a-1=9
	printf("a=%d b=%d", a, b);//9,10


	//(类型):强制类型转换
	int a = 3.14;//从double转换到int,可能会丢失数据,输出结果为3
	int a = (int)3.14;//强制类型转换
	printf("%d\n",a);//输出结果为3

	return 0;
}

关系操作符:
==:相等,是两个等号
逻辑操作符:
逻辑操作符:关注的是真与假
&&和||:逻辑与和逻辑或

int main()
{
	int a = 10;
	int b = 3;
	//不输出
	if (a == 3 && b == 4)
	{
		printf("hehe\n");
	}
	//输出
	if (a == 10 || b == 8)
	{
		printf("haha\n");
	}
	return 0;
}

条件操作符:
exp1?exp2:exp3:如果1为真,运行2;如果1为假,运行3

int main()
{
	int a = 3;
	int b = 5;
	int m = 0;

	m = ((a>b)?a:b);
	printf("%d\n",m);//输出5
	return 0;
}

逗号操作符:
逗号表达式:会从左向右依次计算,整个表达式的结果是最后一个表达式的结果

int main()
{
	int a = 1;
	int b = 3;
	int c = 4;
	int d = (a=b-3,b=a*2,c=a-b);//a=0,b=0,c=0
	printf("%d\n",d);

	return 0;
}

下标引用操作符[ ]:

int main()
{
	int arr[10] = {1,2,3,4,5};//后面会默认补0
	printf("%d\n",arr[8]);//0
	return 0;
}

10.常见关键字

typedef:类型重定义

typedef unsigned int uint;//将unsigned int重命名为uint
int main()
{
	//无符号的整型变量
	unsigned int num1 = 0;
	uint num2 = 0;
	
	return 0;
}

register:寄存器关键字
寄存器:计算机中的一种存储器,是集成到CPU上的
寄存器<-高速缓存(cache)<-内存<-硬盘<-网盘(越往上速度越来越快,造价越来越高)

int main()
{
	register int num = 10;
	//register只是起到一个建议的作用,建议将num的值放在寄存器中,但最终是否放入还是由编辑器决定的
	//寄存器变量是不能取地址的,因为取地址取的是内存的地址,而register是集成在cpu上的,因而是无法取地址的
	return 0;
}

static关键字:
static修饰的局部变量:
static修饰局部变量的时候,改变了局部变量的存储类型,本来一个局部变量是存储在栈区,而被static修饰的局部变量是存储在静态区的;
在栈区上的局部变量,出了作用域生命周期结束,变量被销毁;而被static修饰的局部变量,出了作用域生命周期没有结束,变量也不销毁;
static修饰的局部变量的生命周期和程序的生命周期一样;
static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束
案例一:

void test()
{
	int n = 1;
	n++;
	printf("%d ",n);//n的值不发生变化,为2
}

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

运行结果:
在这里插入图片描述案例二:

void test()
{
	static int n = 1;
	n++;
	printf("%d ",n);//n的值为2,3,4,5,6,7,8,9,10,11
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	return 0;
}

运行结果:
运行结果static修饰的全局变量:
static修饰全局变量的时候,改变了全局变量的链接属性,本来一个全局变量是具有外部链接属性的,但是被static修饰后就变成了具有内部链接属性,这时static修饰的全局变量只能在本源文件(.c)中使用,其他文件无法再使用;
在c中,源文件扮演模块的角色。任何带有static属性声明的全局变量或者函数都是模块私有的。类似的,任何不带static属性的全局变量和函数都是公有的,可以被其他模块访问
案例一:
add.c

int g_val = 10;

test.c

//extern是用来声明外部符号的
extern int g_val;//extern可加可不加

int main()
{
	printf("%d\n",g_val);//10
	return 0;
}

运行结果:运行结果案例二:
add.c

static int g_val = 10;
//test.c函数编译不通过,因为static修饰的全局变量,改变了全局变量的链接属性

test.c

//extern是用来声明外部符号的
extern int g_val;//extern可加可不加

int main()
{
	printf("%d\n",g_val);//运行不通过
	return 0;
}

运行结果:
运行结果static修饰函数:
static修饰函数和修饰全局变量是类似的,一个函数本来也是具有外部链接属性的,当被static修饰的时候,外部链接属性就变成了内部链接属性,这个函数就只能在本源文件内部使用,其他文件不能再使用
案例一:
add.c

//函数也是具有外部链接属性的
int Add(int x, int y)
{
	int z = x + y;
	return z;
}

test.c

//声明来自外部的函数
extern int Add(int,int);

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d",&a,&b);
	int sum = Add(a, b);
	printf("%d\n",sum);
	return 0;
}

运行结果:
在这里插入图片描述案例二:
add.c

//static修饰的函数
static int Add(int x, int y)
{
	int z = x + y;
	return z;
}

test.c

//声明来自外部的函数
extern int Add(int,int);

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d",&a,&b);
	int sum = Add(a, b);
	printf("%d\n",sum);
	return 0;
}

运行结果:
运行结果

10.#define定义常量和宏

#define定义标识符常量

//#define 定义标识符常量
#define NUM 100
#define STR "hehe" 

int main()
{
	printf("%d\n",NUM);//100
	printf("%s\n",STR);//hehe
	return 0;
}

#define定义宏

//#define 定义宏 宏是有参数的
#define ADD(x,y)((x)+(y))//带括号
int main()
{
	int a = 10;
	int b = 20;
	int sum = ADD(a, b);//int sum = ((a)+(b));
	printf("%d\n",sum);//30
	return 0;
}

11.指针

内存:
外存:又叫外部存储器,长期存放数据,掉电不丢失数据
内存:又叫内部存储器,暂时存放数据,掉电数据丢失,又可分为物理内存和虚拟内存。物理内存:实实在在存在的存储设备;虚拟内存:操作系统虚拟出来的内存。在32位系统下,每个进程(运行的程序)的寻址范围是4G,即0x00 00 00 00-0xff ff ff ff。在写应用程序时,我们看到的都是虚拟地址。
在运行程序时,操作系统会将虚拟内存进行分区:
堆区:在动态申请内存时,在堆区开辟内存;
栈区:主要存放局部变量,主要是在函数内部或者复合语句内部定义的变量;
静态全局区:未初始化的静态全局区(静态变量(定义的时候,前面加static修饰)或全局变量在没有初始化时,存放在此区域);初始化的静态全局区(全局变量或静态变量赋过初值的,存放在此区));
代码区:存放咱们的程序代码
文字常量区:存放常量的
内存是以字节为单位来存储数据的,咱们可以将程序中的虚拟存储空间,看成一个很大的一维的字符数组

指针:
系统给虚拟内存的每个存储单元分配了一个编号,从0x00 00 00 00-0xff ff ff ff,这个编号就称之为地址,指针就是地址。

指针变量:是个变量,是个指针变量,即这个变量用来存放一个地址编号;
在32位平台下,地址总线是32位的,所以地址是32位编号,所以指针变量是32位的,即4个字节;
无论什么类型的地址,都是存储单元的编号,在32位平台下都是4字节,即任何类型的指针变量都是4字节大小。
对应类型的指针变量,只能存放对应类型的变量的地址
多字节的变量,对应多个地址编号,编号最小的地址编号就是多字节变量的地址

指针变量的定义方法:

int *p;//在定义指针变量的时候,*是用来修饰变量的,说明变量p是个指针变量,变量名为p

&:取地址;*:取值

int main()
{
	int num = 10;
	&num;//取出num的地址
	printf("%p\n",&num);//打印地址,%p以地址的形式打印

	return 0;
}
int a=0x1234abcd;
int *p=NULL;
P=&a;//p保存了a的地址,也可以说p指向了a
//a的值是0x1234abcd,假如a的地址是:0xbfe89868,则关系图如下图所示
int num;
num=*p;//在调用时,*代表取值的意思,*p就相当于p指向的变量,即a,所以num=*p和num=a的效果是一样的

在这里插入图片描述如果在一行当中定义了多个指针变量,每个指针变量的前面都需要加*来修饰

int *p,*q;//定义了两个整型的指针变量p和q
int *p,q;//定义了一个整型指针变量p,和整型的变量q
int main()
{
	int a = 100, b = 200;
	int* p_1, * p_2 = &b;//表示该变量的类型是一个指针变量,指针变量名是p_1而不是*p_1;
	//p_1在定义的时候没有赋初值,p_2赋了初值
	p_1 = &a;//p_1先定义后赋值
	printf("%d\n",a);
	printf("%d\n",*p_1);

	printf("%d\n",b);
	printf("%d\n", *p_2);

	return 0;
}
//在定义p_1的时候,因为是个局部变量,局部变量没有赋初值,它的值是随机的,p_1指向哪里不一定,所以p_1是个野指针

指针的大小:

32位机器:支持32位的虚拟地址空间,产生的地址就是32bit位的,那么就需要32bit的空间存储->4byte;
64位机器:支持64位的虚拟地址空间,产生的地址就是64bit位的,那么就需要64bit的存储空间->8byte;
32位平台下地址是32bit位(即4个字节);
64位平台下地址是64bit位(即8个字节);

int main()
{
	char ch = 'w';
	int n = 100;
	double d = 3.14;

	char* pc = &ch;
	int* pi = &n;
	double* pd = &d;

	printf("%d\n",sizeof(pc));//4
	printf("%d\n",sizeof(pi));//4
	printf("%d\n",sizeof(pd));//4

	return 0;
}

指针和变量的关系:
*+指针变量:就相当于指针指向的变量

int main()
{
	int* p1, * p2, temp, a, b;
	p1 = &a;
	p2 = &b;
	printf("请输入a,b的值:\n");
	scanf("%d %d",&a,&b);
	temp = *p1;
	*p1 = *p2;
	*p2 = temp;

	printf("a=%d b=%d\n",a,b);
	printf("*p1=%d *p2=%d\n",*p1,*p2);

	return 0;
}

运行结果:
在这里插入图片描述
如果想让不同类型的指针相互赋值的时候,需要强制类型转换;
通用指针void* p:可以存放任何类型的变量的地址编号

int main()
{
	int a = 0x12345678, b = 0xabcdef66;
	char* p1, * p2;
	printf("%0x %0x\n",a,b);
	p1 = (char*)&a;
	p2 = (char*)&b;

	printf("%0x %0x\n",*p1,*p2);

	p1++;
	p2++;
	printf("%0x %0x\n",*p1,(0xff)&(*p2));

	return 0;
}

运行结果:

注意:
*+指针:取值,取几个字节,由指针类型决定的;指针为字符指针则取一个,指针为整型指针择取四个字节,指针为double型指针则取8个字节。
指针++:指向下个对应类型的数据。字符指针++,指向下个字符数据,指针存放的地址编号加1;整型指针++,指向下个整型数据,指针存放的地址编号加4

12.结构体

//定义一个结构体
struct  Stu
{
	char name[20];
	int age;
	char sex[5];
	double score;
};

int main()
{
	struct Stu s1 = {"张三",20,"男",90.5};
	struct Stu s2 = {"如花",40,"女",99.5};

	//输入
	scanf("%s %d %s %lf",s1.name,&(s1.age),s1.sex,&(s1.score));//age和score前面必须要加&

	//方式一
	printf("%s %d %s %lf\n",s1.name,s1.age,s1.sex,s1.score);
	//结构成员访问操作符:结构体变量.结构体成员

	//方式二:
	struct Stu* ps = &s1;
	printf("%s %d %s %lf\n",(*ps).name,(*ps).age,(*ps).sex,(*ps).score);
	//方法三:
	printf("%s %d %s %lf\n",ps->name,ps->age,ps->sex,ps->score);
	//结构成员访问操作符:结构体指针->结构体成员
	
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/19274.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis基础知识点总结

MyBatis了解 MyBatis 是什么&#xff1f; MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集 MyBatis 可以使用简单的XML或注解用于配置和原始映射&#xff0c;将接口和Java的 POJO&#x…

JVM-内存结构

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;JVM &#x1f96d;本文内容&…

Mybatis一级缓存详解

目录 一级缓存 一级缓存的组织 一级缓存的生命周期 一级缓存的工作流程 Cache接口的设计以及CacheKey的定义 一级缓存的性能分析 一级缓存与Spring 事务一级缓存存在的弊端 官方文档分析 Spring通过Mybatis调用数据库的过程 一级缓存 对于会话&#xff08;Session&am…

chanmama响应数据解析

0x00目标url aHR0cHM6Ly93d3cuY2hhbm1hbWEuY29tL2F1dGhvckRldGFpbC85OTI0MjExODcxOC9wcm9tb3Rpb24 0x01接口分析 简单的get 但是返回数据被加密了 这里我们就来想想怎么解密这些数据。首先后端发来的数据是加密的&#xff0c;但是我们在前端看到的可不是加密后的数据。前端…

什么是零拷贝?

零拷贝 什么是零拷贝 零拷贝指的是&#xff0c;从一个存储区域到另一个存储区域的copy任务无需CPU参与就可完成。零拷贝的底层是 通过DMA总线技术实现的。零拷贝与具体的编程语言无关&#xff0c;完全依赖于OS&#xff0c;OS支持就可使用&#xff0c;不支持 设置了也不起作用…

大厂视频面试,因为截屏作废

大厂视频面试现在这么严格了么&#xff1f;无意间按到截屏直接显示面试作废&#xff0c;好在最后和HR解释了下&#xff0c;再约时间重新面。 作为一个面试过3、4家大厂&#xff0c;现在在鹅厂工作的过来人来说&#xff0c;上面遇到的这个问题是AI面&#xff0c;不用太担心&…

笔记本电脑开机黑屏没反应怎么办?

笔记本电脑开机黑屏没反应怎么办&#xff1f;有用户电脑开机之后&#xff0c;桌面会变成黑屏显示。而且是常常都会出现这样的问题&#xff0c;非常影响自己的电脑使用体验。那么遇到这个问题要怎么去进行问题的解决呢&#xff1f;来看看以下的解决方法吧。 准备工作&#xff1a…

玩游戏时突然弹出”显示器驱动程序已停止响应并且已恢复”怎么办

随着3A游戏大作不断面市&#xff0c;用户也不断地提升着自己的硬件设备。但是硬件更上了&#xff0c;却还会出现一些突如其来的情况&#xff0c;比如正准备开启某款游戏时&#xff0c;电脑右下角突然出现“显示器驱动程序已停止响应并且已恢复”。遇事不慌&#xff0c;驱动人生…

java lambda表达式详解

一、Lambda初识 我们知道&#xff0c;在Java中&#xff0c;接口是不能实例化的&#xff0c;但是接口对象可以指向它的实现类对象。如果接口连实现对象都没有呢&#xff1f;那还可以使用匿名类的方式&#xff0c;如下: public class JavaTest { public static void main(Strin…

某程序员哀叹:二本计算机,4年开发,年包才40多万。二本真的不如985/211吗?

前段时间&#xff0c;某职场论坛上有人发了一个帖子&#xff0c;发帖人问&#xff1a;为什么大家工资那么高&#xff0c;三五年都六七十万了&#xff1f;我二本计算机专业&#xff0c;四年前端开发&#xff0c;找个年包40万多点就顶头了。 原贴如下&#xff1a; 有网友表示楼主…

2022年平均工资出炉,IT行业又是第一

根据5月9日国家统计局最新资料显示&#xff0c;2022年&#xff0c;全国城镇非私营单位就业人员年平均工资为114029元&#xff0c;比上年增长6.7%&#xff0c;扣除通胀后实际增长4.6%。其中&#xff0c;行业间的差距相当明显。根据资料显示&#xff0c;2022年无论是在私营单位还…

Android---bitmap优化

目录 Bitmap 占用内存大小计算 Bitmap | Drawable | InputStream | Byte[] 之间进行转换 Bitmap 相关方法 BitmapFactory 工厂类 Bitmap 占用内存大小计算 Bitmap 作为位图&#xff0c;需要读入一张图片中每一个像素点的数据&#xff0c;其主要占用内存的地方也正是这些像…

python进阶--月考二

python进阶--月考二 &#xff08;一&#xff09;装饰器&#xff08;二&#xff09;创建名为express.py文件&#xff0c;编写以下推导式&#xff08;25分&#xff09;&#xff08;三&#xff09;创建名为process_test.py的文件&#xff0c;计算1-3000之间的水仙花数&#xff08;…

QT MD4 MD5 Sha1等几种加密方式

QT MD4 MD5 Sha1等几种加密方式 [1] QT MD4 MD5 Sha1等几种加密方式[2] qt MD5 和AES 加密一 、MD5 加密二、AES 加密和解密 [3] QT中sqlite数据库数据加密/混淆---MD5/SHA1/SHA2/SHA3&#xff08;1&#xff09;创建一个加密对象&#xff08;2&#xff09;放入要加密的数据&…

目前可用的ChatGPT网站

本文意在整理可用gpt-3.5、gpt-4.0等网站。 本文主要是方便自己翻阅&#xff0c;如对您也有所帮助&#xff0c;不胜荣幸~ 文章目录 chatgpt.qdymys.cngpttalkchatgpt-cn.cobing.comchat机器人wuguokai.cn总结 chatgpt.qdymys.cn 网址&#xff1a;https://chatgpt.qdymys.cn/限…

SpringCloud —— eureka

目录 1.认识微服务 1.0.学习目标 1.1.单体架构 1.2.分布式架构 1.3.微服务 1.4.SpringCloud 1.5.总结 2.服务拆分和远程调用 2.1.服务拆分原则 2.2.服务拆分示例 2.2.1.导入Sql语句 2.2.2.导入demo工程 2.3.实现远程调用案例 2.3.1.案例需求&#xff1a; 2.3.2.注…

mysql进阶-查询优化-慢查询日志

文章目录 一、什么是慢查询日志二、慢查询日志能干什么2.1 性能分析和优化2.2 诊断和排查问题2.3 数据分析和探索 三、慢查询日志实战3.1 永久开启开启慢查询日志3.2 临时开启慢查询日志3.4 常用命令 四、如何分析慢查询日志五、优化慢查询语句五、总结 一、什么是慢查询日志 …

观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

文章目录 概念组成角色相关图示示例代码框架中的运用适用场景 概念 观察者设计模式&#xff08;Observer Design Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种对象间的一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象&#xff0c;当…

SpringBoot 配置文件

前言&#xff1a; 本篇主要介绍两种配置文件格式&#xff0c;分别为properties与yml(yaml)。 需要注意的是&#xff1a; 两个配置文件从功能上来讲是可以同时存在的&#xff0c;但是企业中通常会规定使用某一种格式的配置文件。如果同一个配置出现在两种格式的配置文件中的话&a…

微波方向有哪些SCI期刊推荐? - 易智编译EaseEditing

微波方向的SCI期刊推荐包括&#xff1a; IEEE Transactions on Microwave Theory and Technology&#xff1a; 该期刊是电磁场与微波技术领域的著名期刊&#xff0c;被世界上许多研究机构和大学广泛引用。 IEEE Transactions on Antennas and Propagation&#xff1a; 该期刊…