LinuxC学习保姆级教程(李慧芹课程笔记)_史上最强最细腻的linux嵌入式c语言学习教程【李慧芹老师】-程序员宅基地

技术标签: c语言  linux  vim  嵌入式工程师学习之路  

一、课前准备

1.Linux和unbutu安装

微信关注 软件管家 公众号->回复Linux->点击虚拟安装Linux系统教程

2.虚拟机联网

VMware虚拟机不能联网的解决办法

3.gcc和vim的安装及使用说明

首先按 :ctrl+shift+T 打开终端
输入sudo apt install gcc
接着输入Ubuntu密码(之前设置的密码)
就可以安装gcc啦

4.做一个简单的例程感受一下吧

(1)首先创建一个vim吧(vim可以理解为一个word文档编辑器)
vim这个编译器有许多快捷键,不掌握这些快捷键是很难完成编译的 vim入门教程
1.输入vim hello.c
在这里插入图片描述
2.进入vim后,按 a 进入编辑模式,输入下面的代码

#include<stdio.h>
#include<stdlib.h>

int main()
{
           
printf("Hello Wold!\n");
exit(0);
}

3.按 esc 键,退出编辑模式。再输入 :qw保存并退出
4.终端输入 gcc hello.c -o hello 编译器会自动编译hello.c 并生成一个 hello文件
在这里插入图片描述

5.输入 ./hello 运行hello这个文件
在这里插入图片描述

看到Hello word! 就算成功运行这个程序啦!
下面可以进入C语言的学习啦

二、数据类型

1.常量

(1) 整形常量:1,79
实型常量:3.14,1.999
字符常量:由单引号引起来的单个字符或转意字符’a’,’\n’,’\015’(八进制)
,’\x7f’(十六进制)

(2).字符串常量:由双引号引起来的一个或多个字符串组成的序列
如"",”a”,”asdXS\n\021”

(3)1标识常量(特点:处理在程序预处理阶段,一改全改,但不检查语法,只是单纯宏体与宏名替换)
a) #define PI 3.14(用宏体替换为宏名)
b) #define ADD 2+3(直接转换到上面)
c) #define MAX(a,b) (a>b?a:b)

(4). 什么时候用宏,什么时候用函数
答:节约时间用宏,保证稳定用函数

2.变量

定义:用来保存一些特定的内容,并且在程序执行过程中随时发生变化的量

1. 存储类型:auto static register extern(说明型)

a) auto:默认,自动分配空间,自动回收空间
b) register:(建议型)寄存器类型 只能定义局部变量,不能定义全局变量,只能定义32位大小的数据类型,寄存器没有地址,所以寄存器类型的变量无法打印出地址查看或使用 sush register int i=1
c) static:静态型,自动华初始值为0或NULL,并值其变量的值有继承性,仅能在局部使用。
d) extern:说明型,意味着不能改变被说明变量的值或类型

2.变量的生命周期和作用范围

a) 全局变量和局部变量
全局:从定义开始到程序结束
局部:从当前程序块开始,到程序块结束
b) 局部变量和局部变量
内部优先

3.运算符和表达式

运算符 符号
1.单目运算符 +、- 、 *、 \、 % 、 ++、 – 、 % 、/
关系运算符 < <= >= !=
逻辑运算符! &&(有零取零) 异或(有1取1)
注意:短路特性 &&左边为0,
赋值运算符 = (a = 3 -> a = a3)
条件运算符 ? :
逗号运算符
求字节数sizeof 例:printf(“%d\n”,sizeof(int));
强制类型转换 例:a=(int)f;
位运算的重要意义 硬件、电路很多都用位运算
移位操作 <<(右移)
  ~(取反)  
|(按位或,有1取1) 
 ^(按位异或,同值取零不同取一)
&(按位与,有零取零)

例:  将操作位中第n位置1 num=num | 1<<n
	将操作数中第n位清0,其他位不变:num=num&~(1<<n)
	测试第n定位:if(num & 1 <<n)
	从一个指定宽度中取出其中某几位???:段中取出几位	

三、输入、输出专题

1、格式化输入输出函数:scanf、printf
int printf(const char *format,)
format :"% [修饰符] 格式字符",

输出格式 字符
十进制整数 %d
十六进制无符号整数 %x
八进制 %o
不带符号十进制整数 %u
单一字符 %c
字符串 %s
指数形式浮点数 %e
百分号本身 %%
修饰符 功能
m 输出数据宽度,数据长度<m,左补空格,否则按实际输出
.n 对实数,指定指定小数点后位(四舍五入)
.n 对字符串,指定实际输出位
- 输出数据左对齐(缺省右对齐)
+ 指定在该符号数的整数正数前显示正号(+)
0 输出数值时指定左面不适用的空位自动添零
# 在八进制和16进制前显示前导0,0x
l 在d,o,x,u前指定输出精度为long型
l 在e,g,f前,指定输出精度为double型

printf和scanf的注意事项

printf("%s,%d\n",__FUNCTION__,__LINE__)

/* \n有强制刷新缓冲区的作用==查错时printf习惯性加\n 
scanf("%d",&i)
//%s慎用,超出会发生越界,因为不知道存储空间大小
scanf放在循环很危险,注意能否接收到正常有效的内容,输出加\n
一般情况输入什么你就里面写什么
scanf("")

2、字符串输入输出函数:getchar、putchar
getchar,回收字符,尤其时功能字符回车、空格等
3、字符串输入输出函数:gets(!)的、对缓冲区不做检查,puts
最好不用gets,用getline

四、流程控制

顺序、选择、循环
NS图,流程图 工具Dia
简单结构与复杂结构:自然流程

  1. 顺序:语句逐句执行
  2. 选择:出现一种以上情况
  3. 循环:在某个条件成立的情况下,重复执行某个动作

关键字:
选择:if-else switch-case
循环:while do-while for if-goto
辅助控制:continue break

1.详解:if-else:

格式 if (exp)
cmd;
else if(exp)
cmd;
注意:else只找与它最近的if相匹配

2.详解 switch-case

语法格式:
switch(exp)
{
case 常量表达式
break;
case 常量表达式
break;

default:
}
3.详解循环:while
while 最少循环0次
do-while 至少循环1次

4.for:(最少循环0次)

佛如(exp1;exp2;exp3)
loop;
if-goto:(慎用:go-to实现的是无条件的跳转,且不能跨函数跳转)

5.死循环:

while(1);
for( ; ; );
杀死死循环ctrl+c

6.辅助控制关键字: break continue

break跳出本层循环
continue跳出本次循环

选择循环练习题

(1)投资问题:以每年10%的单利息投资了100美元,B以每年5%的符合利息投资了100美元。编写一程序,计算要多少年B的投资总额会超过A的,并且显示出到那个时候两个人的各自总资产

(2)从终端读入数据,直到输入0值为止,计算出其中的偶数的个数及平均值和奇数的个数及平均值
(3)从终端输入若干字符,对其元音字母进行统计
(4)写出斐波那契数列的前40项(不能用数组实现)

1 1 2 3 5 8 13 21 。。。

(5)输出九九乘法表
(6)百钱买百鸡:鸡翁一,值钱5;鸡母一,值钱三;三鸡雏,值钱一,问鸡翁,鸡母,鸡雏各几何?
#include<stdio.h>
#include<stdlib.h>
static void text6(void)
{
    
	int x,y,z,s;
	for(x=0;x<20;x++)
	{
    
		for (y=0;y<100/3;y++)
		{
    
			z=100-x-y;
			s=5*x+3*y+z/3;
				if(s==100&&z%3==0)
				{
    
					printf("man=%d\twoman=%d\tchlidren=%d\n",x,y,z);
				}
		}
	}
}
int main()
{
           
	text6();
	exit(0);
}
(7)求出1000以内的水仙花数(各位数的立方和为数本身)如153=1+125+27
static void text7(void)
{
    
	int i;
	int a,b,c;
	for(i=100;i<1000;i++)
		{
    
			a=i/100;
			b=i%100/10;
			c=i%10;
			if(a*a*a+b*b*b+c*c*c==i)
       			 printf("The narcissistic number is:%d\n",i);
		}
}
(8)求出1000以内的所有质数:2,3,5,7,11,13,17,19…
static void text8(void)
{
    
	int i,j,mark;
	for(i=2;i<1000;i++)
	{
    
	        mark=1;
	        for(j=2;j<i/2;j++)
	        {
    
	                if(i%j==0)
	                {
    
	                        mark=0;
	                        break;
	                }
	        }
	        if (mark)
	                printf("The prime number is:%d\n",i);
	}
	return;
}
(9)在终端实现如下输出:

ABCDEF
BCDEF
CDEF
DEF
EF
F

static void text9(void)
{
    
	int line=6,chars=6;
	int i;
	char ch;
	for(i=0;i<line;i++)
	        {
    
	        for(ch='A';ch<'A'+chars;ch++)
	                {
    
	                printf("%c",ch);
	                }
	        printf("\n");
	        chars--;
	        }
}
(10)在终端输出钻石型
(11)之终端输入N个数(以字母Q/q作为终止),求和。
//注意:不只有输入q才会退出,只要输入不符合scanf的格式的都会退出
static void text11(void)
{
    
        int sum=0;
        int num;
        printf("Please enter the first integet(q to quit)");
        while(scanf("%d",&num)==1)
                {
    
                        if(num=='q')
                                break;
                        sum+=num;
                        printf("Please enter other intget:");
                }
                printf("sum=%d",sum);
}
(12)从半径为1开始,输出圆的面积,直到圆的面积为100截至
static void text12(void)
{
    
        int r=1;
        float area;
        for(area=1;area<=100;r++)
        {
    
                area=r*r*PI;
                if(area>100)
                        break;

                printf("area is %f\n",area);

        }

五、数组

1.一维数组

(1)定义

【存储类型】数据类型 标识符 【下标】
 特点:在内存中连续存放
 理解:就是一个变量,连续存放

(2)初始化

部分元素初始化,初始化的函数该是多少就是多少,其他数为零
数组不能无条件出现在等号左边

(3)元素引用

数组名 【下标】

(4)数组名

	数组名是表示地址的常量

(5)数组越界

数组越界不检查。靠程序员自身敏感程度

数组学习代码

#include<stdio.h>
#include<stdlib.h>
#define M 3
int main()
{
    
        int i;
        int arr[M];
        printf("%ld\n",sizeof(arr));
        for(i=0;i<M;i++)
                printf("%p-->%d\n",&arr[i],arr[i]);
        exit(0);
}

1.斐波那契数列

#include<stdio.h>
#include<stdlib.h>
#define a 10
int main()
{
    
        int i;
        int arr[a]={
    1,1};
        for(i=2;i<10;i++)
                arr[i]=arr[i-1]+arr[i-2];
        for(i=0;i<10;i++)
                printf("%d ",arr[i]);
        exit(0);
}

2.数据排序:
冒泡,每次只判断一个数,比大小,朝前或朝后移动(小数慢慢浮起来,大数沉下去慢慢)

#include<stdio.h>
#include<stdlib.h>
#define N 10
static void sort1(void)
{
    
        int i,j,tmp;
        int a[N]={
    45,48,24,46,68,48,24,33,1,2};
        for(i=0;i<N;i++)
                printf("%d ",a[i]);
        printf("\n");
        for(i=0;i<(N);i++)
        {
    
                for(j=0;j<(N-i);j++)
                {
    
                        if(a[j]>a[j+1])
                        {
    
                                tmp=a[j];
                                a[j]=a[j+1];
                                a[j+1]=tmp;
                        }
                          }
        }
        for (i=0;i<N;i++)
                printf("%d ",a[i]);
        printf("\n");
}
int main()
{
    
        sort1();

}



选择法,快速排序(一个数据串中,找到最小的放在第一位)

3.进制转换、

//最后一个for循环有问题,一直没改对
static void base_convert(void)
{
    
        int i=0;
        int num,base,a[N];
        printf("Please enter the converted num:");
        scanf("%d",&num);
        printf("Please enter the base:");
        scanf("%d",&base);
        do
        {
    
                a[i]=(num%base);
                num=num/base;
                printf("%d ",a[i]);
                i++;
                printf("i=%d",i);
        }while(num != 0);
        printf("\nB");
        printf("end i=%d",i);
for(;i>=0;i--)
        {
    
                printf("%d",a[i]);
        }
}

4.删数法求质数


2.二维数组

(1)定义

【存储类型】 数据类型 标识符 【行下标】 【列下标】
数组名即为数组起始位置
例:int M[2][3]   两行三列的数组 
在存储空间按行存放如:M[0][1] M[0][2] M[1][0] M[][1] M[0][1]
部分数组初始化:int a[3][3]={
   {1,2}{5,6}}
全部数组初始化:int a[3][3]={
   {1,2,3},{4,5,6},{7,8,9}}
定义可以行省略:例如:int a[][N]={4,8,45,65,8}

(2)元素引用

例:
1.行列互换

include<stdio.h>
#include<stdlib.h>
#define N 3
#define M 2
static void change(void)
{
    
        int i,j;
        int a[M][N]={
    1,2,3,4,5,6},b[N][M];
        for(i=0;i<M;i++)
        {
    
                for(j=0;j<N;j++)
                {
    
                        printf("%d",a[i][j]);
                        b[j][i]=a[i][j];
                }
                printf("\n");
        }
        for(i=0;i<N;i++)
        {
    
                for(j=0;j<M;j++)
                        printf("%d",b[i][j]);

                printf("\n");
        }
}
int main()
{
    
        change();
        exit(0);
}

2.求最大值及其所在位置

3.求各行与各列的和

static void sum(void)
{
    
        int i,j;
        int a[3][4]={
    {
    1,2,3},{
    4,5,6}};
        for(i=0;i<2;i++)
        {
    
                for(j=0;j<3;j++)
                {
    
                        a[2][3]+=a[i][j];
                        a[2][j]+=a[i][j];
                        a[i][3]+=a[i][j];
                        printf("%4d",a[i][j]);
                }
                printf("\n");
        }
        for(i=0;i<3;i++)
        {
    
                {
    
                        for(j=0;j<4;j++)
                                printf("%4d",a[i][j]);
                }
                printf("\n");
        }
}

4.矩阵乘积

(3)存储形式

在一块空间连续存储

在这里插入图片描述

(4)深入理解二维数组

二维数组,本质上是多个一维数组组成的
主要是理解行指针和列指针

3. 字符数组

1.定义,初始化,存储特点

【存储类型】 数据类型 标识符 【行下标】 【列下标】

2.单个字符初始化

	
输入语句:char str[N]={
    'a','b','c'};
输出语句:for(i=0;i<N;i++)
printf("%c,str[i]");

3.字符串常量初始化

	
int main()
{
    
	int N=3;
	char str[N];
	gets(str);
	puts(str);
}
上面这段代码很危险,虽然程序可以运行,但是如果输入超过2个字符
(系统会自动加一个尾零),之后的存储空间如果被保护过,则会发生段错误;

4.输入输出

scanf("%s",str);
printf("%s",str);
注意%s无法获得带分隔符的字符串

例如:
输入 hello word
输出为 hello

输入可以改为scanf("%s%s",str)来解决这个问题;

5.常用函数

为什么字符串有常用函数,而整形,浮点型等其他类型不需要函数呢

因为int等类型可以用if来比大小,也可以相互赋值,但是字符串的名字就是一个地址常量,没办法比较大小,赋值等操作,所以需要常用函数来解决这些问题

不能直接复制 例如: str=“abcde”,这个是不成立的
(1)strlen
作用:以尾零作为结束,显示当前字符串个数 (输入Hello word,返回值为5)

printf("%d\n",strlen(str))

(2)sizeof
作用:该字符串在内存所占字节个数 (输入Hello word,返回值为11)

printf("%d\n",sizeof(str));

(3)strcpy

用法strcpy(str,"abcde"); 作用:将abcde字符串copy到str中
puts(str);

(4)strncpy

用法:strncpy(str,“abcde”,STRSIZE); 作用:将abcde字符串copy到
str中,但是STRSIZE会限制copy个数,防止溢出

(5)stract

 char *strcat(char *dest, const char *src);
 作用:将两个字符串首尾连接

(6) strncmp

int strcmp(const char *s1, const char *s2);
作用:比较ASCLL码大小,根据比较大小情况,返回值为1,0,-1

6.字符数组的单词计数

计算有多少字符串

#include <stdio.h>
#include<stdlib.h>
int main()
{
    
        char str[128];
        int flag=0,count =0;
        int i;
        gets (str);
        for (i=0;str[i]!='\0';i++)
        {
    
                if(str[i]==' ')
                        flag = 0;
                else if(flag==0)
                {
    
                        count++;
                        flag =1;
                }
        }
        printf("count=%d\n",count);
        exit(0);
}

4.多维数组

就是一维二维数组的递推
int a[2][3][4];

六、指针

1.变量与地址

变量名int i 这里的i是给程序员看到,i是一个抽象的地址

2.指针与指针变量

定义:[数据类型] *p=&i;
int *i=1;
int *p;
char *c
doubule *c
无论是什么类型的指针,所占字节数sizeof(c),均为8
虽然指针所占字节,指针变量和他所指类型的值,一定要相符

例子

#include <stdio.h>
#include<stdlib.h>
int main()
{
    
        int i=1;
        int *p;
        p=&i;
        printf("i=%d\n",i); 	//输出i的值
        printf("&i=%p\n",&i);	//i的地址
        printf("p=%p\n",p );	//p的值,存放的是i的地址
        printf("&p=%p\n",&p);	//	p的地址,一块独立的指针空间
        printf("*p=%p\n",*p);		//p所指的i中的内容
        exit(0);
}

3.直接访问与间接访问

在这里插入图片描述

	上图中:q=0x3000=&p
		    p=0x2000=&i
		   	i=1
		   	&q=0x4000
		   	*q=*(&p)=p=&i
		   	**q=*(&i)=i=1
	如果能理解上述关系,指针这里基本就没问题了	
	想访问i的值,可以通过i  *p  **q三种形式访问
	想访问i的地址,可以通过 &i  p  *q三种形式访问

4.空指针与野指针

指针定义:int *p =NULL (指针定义为NULL,是防止野指针的产生,如果你不清楚指向谁,就定义指针为NULL)
野指针是非常危险的,一定要让指针有去处

5.空类型

void *q=NULL (void类型的指针是一个万金油,它与任何指针类型都可以相互赋值)

6.定义与初始化的书写规则

int i=1:
int *p=&i
int **q =&i

7.指针与运算

指针的运算较少只有  &(取地址)  *(取值)  关系运算  ++  --

8.指针与数组

(1).指针与一维数组

#include <stdio.h>
#include<stdlib.h>
int main()
{
    
        int a[3]={
    1,2,3};
        int *p=a;
        int i;
        for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
        	printf("%d",a[i])
        printf("\n");
        exit(0);         
}
(1)a[i] = *(a+i) = *(p+i)= p[i]
a是数组名,是常量不可以做赋值变换,例如a++
但是p是一个指针,可以做赋值变换,p++
注意:p++和p+1的区别
学会数组常量和数组变量的区别

(2).指针与二维数组

在行上的指针和在列上的指针

#include<stdio.h>
#include<stdlib.h>
int main()
{
    
        int a[2][3]={
    123456};
        int i,j;
        for()
        3
        printf("%ld\n",sizeof(arr));
        for(i=0;i<M;i++)
                printf("%p-->%d\n",&arr[i],arr[i]);
        exit(0);
}

(3).指针与字符数组

9.const与指针

这部分李老师讲的非常好,一听就懂

#define PI 3.14
const float PI=3.14
宏定义和const可以代替使用,区别是宏定义不做检测,const检查

(1)常量指针

用处,在封装一些函数时常用这种方式进行封装,因为其他人不可以通过指针来修改函数

const int *p
int const *p

int i=1;
const int *p =&i;
正确:  i=10;//可以
错误:*p=10;//不可以
作用:保护*p不变,*p是只读的

(2)指针常量

int *const p;
int i=1;
int j=10;
int *const p =&i;
正确:*p=10;//可以改p指向地址里的值
错误:p=&j;
作用:指针变量指的东西不变
fopen:拷贝一块内存数据

口诀:常量指针不可以该值,指针常量,不可以改指针
例如:定义 const int *const p = &i;此时既不能改变指针里的值,又不能改变指针的指向

10.指针数组与数组指针

(1)数组指针(一个指针,指向数组)

定义:【存储类型】 数据类型 (*指针名) 如:int [3] *p 
int main{
int a[2][3]={1,2,3,4,5,6};
int i,j;
int *p=*a;
int (*q)[3]=a;
for()
}

(2)指针数组(n个指针挨在一起)

int *arr[3]={3,5,7}

11.多级指针

不常用

七、函数

1.函数的定义

数据类型 函数名【数据类型 形参名,数据类型 形参名。。。。。】
int (返回的数据类型)  arr  (int argc,char *argv[] )
return 0; (结束当前函数)

argc 是 argument count的缩写,表示传入main函数的参数个数;

argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,并且第一 个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;

2.函数的传参

include<stdio.h>
#include<stdlib.h>
int value(int a,int b)
{
    
        printf("%d %d\n",a,b);
        return 0;
}
int main()
{
    
        int i=3,j=5;
        value(i,j);
        return 0;
}

(1)值传递

用一个程序来解释值传递和地址传递的区别

#include<stdio.h>
#include<stdlib.h>
void swp(int i,int j)
{
    
        int tmp;
        tmp =i;
        i=j;
        j=tmp;
}
int main()
{
    
        int i=3,j=5;
        int tmp;
        swp(i,j);
        printf("%d\t%d\n",i,j);
        return 0;
}
此条语句输出还是i=3,j=5并没有起到交换i与j的作用,如下图,只是新开辟出一块地址,进行了交换,仅i,j名字是一样的,但根本不是一回事

在这里插入图片描述

(2)地址传递

void swp(int *p,int *q)
{
    
        int tmp;
        tmp =*p;
        *p=*q;
        *q=tmp;
}
int main()
{
    
        int i=3,j=5;
        int tmp;
        swp(&i,&j);
        printf("%d\t%d\n",i,j);
        return 0;
}
上面这个函数达到了交换数的目的,通过另外一个函数达到修改其他函数的目的,一般用地址传递

在这里插入图片描述

(3)全局变量

3.函数的调用

(1)嵌套调用

嵌套调用小例子:

#include<stdio.h>
#include<stdlib.h>
int max(int a,int b,int c)
{
    
        int tmp;
        tmp= a>b ? a:b;
        return tmp>c?tmp:c;
}
int min(int a,int b,int c)
{
    
        int tmp=a>b ? b:a;
        return tmp>c ? c:tmp;
}
int dist(int a,int b,int c)
{
    
        return max(a,b,c)-min(a,b,c);

}
int main()
{
    
        int res;
        int a=3,b=5,c=10;
        res = dist(a,b,c);
        printf("res=%d\n",res);
        return 0;
}

(2)递归

递归:一个函数,直接或间接调用自身
一个递归小程序:
FUNCTION:该函数的作用此时运行函数的函数名

#include<stdio.h>
#include<stdlib.h>
int b()
{
    
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]b()end!\n",__FUNCTION__);
        return 0;
}
int a()
{
    
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]call b()!\n",__FUNCTION__);
        b();
        printf("[%s]b() returned!\n",__FUNCTION__);
        printf("[%s]end!\n",__FUNCTION__);
        return 0;
}
int main()
{
    
        printf("[%s]begin!\n",__FUNCTION__);
        printf("[%s]call a()!\n",__FUNCTION__);
        a();
        printf("[%s]a() returned!\n",__FUNCTION__);
        printf("[%s]end!\n",__FUNCTION__);
        return 0;
}

例题:求一个数的阶乘

unc(int n)
{
    
        if (n==1||n==0)
                return 1;
        return  n*func(n-1);
}
int main()
{
    
        int n;
        int res;
        scanf("%d",&n);
        res =func(n);
        printf("n!=%d",res);
        return 0;
}

4.函数与数组

(1)函数与一维数组

#include<stdio.h>
#include<stdlib.h>
void print_arr (int *p)
{
    
int i;
printf("%s:%d\n",__FUNCTION__,sizeof(p));
}
int main()
{
    
int a[]={
    1,3,5,7,9};
printf("%s:%d\n",__FUNCTION__,sizeof(a));
print_arr(a);
exit(0);
}

(2)函数与二维数组

5.函数与指针

八、构造类型

1.结构体

(1)产生及意义

数组只能存储一种类型,结构体可以存储多种类型

(2)类型描述

struct 结构体名字
{
数据类型 成员1;
数据类型 成员2;

};
结构体定义在函数外(少数编译器不允许编译在函数内部)

(3)嵌套定义

定义方式一,分开定义

struct birthday_st
{
    
        int year;
        int month;
        int day;
};
struct student_st
{
    
        int id;
        char name[NAMESIZE];
        int year,month,day;
        int math;
        int chinese;
};

定义方式二,内部定义

struct birthday_st
{
    
        int year;
        int month;
        int day;
};
struct student_st
{
    
        int id;
        char name[NAMESIZE];
        struct birth
        int year,month,day;
        int math;
        int chinese;
};

(4)定义变量(变量,数组,指针),初始化及成员引用

int main()
{
strunct simp_st a={123,456.789,‘a’};
a.i=112233;
printf("%d %f %c\n",a.i,a.f,a.ch);
exit(0);

}

(5)占用内存空间大小

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43892462/article/details/122292299

智能推荐

对计算机相关领域及前沿技术的认识,计算机专业教育及新技术讲座(对计算机专业的认识)论文.pdf...-程序员宅基地

文章浏览阅读1.3k次。《计算机专业教育及新技术讲座》课 程 论 文题目 对计算机专业的认识学 院 : 计算机科学与工程学院专 业 : 计算机科学与技术班 级 : 1103070A学 号 : 1110307..._计算机科学与技术论文讲座内容

舞伴配对问题java_数据结构--队列实现舞伴配对问题+(舞伴程序++c++).doc-程序员宅基地

文章浏览阅读377次。#include#include const bool TURE=1;const bool FAULT=0;using std::cout;using std::cin;using std::endl;class Node{//链式堆栈的节点类public:Node();//构造函数重载1Node(int , int , int ,Node *);//构造函数重载2void const get_d..._java顺序队列跳舞匹配

AB - 模拟/实现并发请求 - PHP (代码) - 压力测试_ab工具模拟并发-程序员宅基地

文章浏览阅读8k次,点赞2次,收藏9次。模拟并发请求, 来测试api性能---压力测试以及需要后端[如: php ]直接请求远程服务器[调用远程服务],但是需求是一次发送多个请求._ab工具模拟并发

Oracle SQL开发 之 Select语句完整的执行顺序-程序员宅基地

文章浏览阅读4次。查询语句语法:Select 属性From 表Where 条件Group by 分组条件Having 分组选择条件Order by 排序条件1、from子句组装来自不同数据源的数据;2、where子句基于指定的条件对记录行进行筛选;3、group by子句将数据划分为多个分组;4、使用聚集函数(列函数)进行计算;5、使用having子句筛选分组;6、计算所有的表达式,主要是sele...

基于Java的大学兼职教师管理系统(Vue.js+SpringBoot)-程序员宅基地

文章浏览阅读620次,点赞16次,收藏14次。大学兼职教师管理系统,旨在提高高校兼职教师的管理效率和准确性。该系统包括教师信息管理、授课管理、班级管理、课程评价管理等模块,通过对兼职教师的基本信息、班级状况和成绩评估进行集中管理,实现各种管理目标。该系统还具有良好的用户体验和便利性,允许管理员轻松完成每项任务,兼职教师也可以通过该系统查看他们的个人信息和课程状态。最后,通过实际应用验证了该系统的可行性和有效性,表明该系统能够满足高校兼职教师管理的需要。

【Unity实战】实现强大通用易扩展的对话系统(附项目源码)(2023/12/26补充更新)_游戏对话系统源码-程序员宅基地

文章浏览阅读4.9k次,点赞35次,收藏83次。本文是参考b站麦扣老师比较老的课程了,我已经看完了,后面发现`缺失`了挺多功能的:* 比如扩展性不好,多NPC很难将对话分开* 快速显示的实现过于麻烦了* 对话框显示在世界坐标,UI无法适配屏幕的变化* 文本只支持显示内容,不支持显示角色名称和人物的不同表情变化_游戏对话系统源码

随便推点

EPOLL 事件之 EPOLLRDHUP-程序员宅基地

文章浏览阅读1.2w次,点赞10次,收藏17次。在对系统问题进行排查时,我发现了一个奇怪的现象:明明是对方断开请求,系统却报告一个查询失败的错误,但从用户角度来看请求的结果正常返回,没有任何问题。对这个现象深入分析后发现,这是一个基于 epoll 的连接池实现上的问题,或者说是特性 :)首先解释一下导致这个现象的原因。在使用 epoll 时,对端正常断开连接(调用 close()),在服务器端会触发一个 epoll 事件_epollrdhup

java计算机毕业设计迅腾游戏交流网站源码+系统+lw+数据库+调试运行-程序员宅基地

文章浏览阅读70次。java计算机毕业设计迅腾游戏交流网站源码+系统+lw+数据库+调试运行注意:该项目只展示部分功能,如需了解,文末获取源码地址。临近学期结束,还是毕业设计,你还在做java程序、网络编程。课程设计,老师的毕设要求觉得大了吗?不知道毕业设计该怎么办?系统功能的数量是否太多?没有合适的类型或系统?等等。这里,你想解决的问题,都能满足你的系统需求。原始Jsp,SSM、SpringBoot,以及HTML+CSS+JS页面设计,web毕设、课程设计源码等等都可以参考得到解决。系统功能:首页个人中心游戏分类管理游

X - 24_he needs a program which, when given a list of wee-程序员宅基地

文章浏览阅读252次。DescriptionThe whole family was excited by the news. Everyone knew grandpa had been an extremely good bridge player for decades, but when it was announced he would be in the Guinness Book of Wor_he needs a program which, when given a list of weekly rankings, finds out wh

向量间的距离和范数到线性空间、赋范空间、內积空间_向量之间的距离-程序员宅基地

文章浏览阅读6.2k次,点赞2次,收藏17次。参考: https://baike.baidu.com/item/%E8%B5%8B%E8%8C%83%E7%A9%BA%E9%97%B4/2285667?fr=aladdin http://blog.csdn.net/mr_hai_cn/article/details/53207307#reply http://blog.csdn.net/soudog/article/details/20..._向量之间的距离

php中浮点数计算问题-程序员宅基地

文章浏览阅读61次。 如果用php的+-*/计算浮点数的时候,可能会遇到一些计算结果错误的问题,比如echo intval( 0.58*100 );会打印57,而不是58,这个其实是计算机底层二进制无法精确表示浮点数的一个bug,是跨语言的,我用python也遇到这个问题。所以基本上大部分语言都提供了精准计算的类库或函数库,比如php有BC高精确度函数库,下面达内php培训老师介绍一下一些常用的BC高精确度函数使用。..._0.58*100.0等于57.99999999999999的解决方案

excel运行python_使用PyXLL在Excel中执行Python脚本-程序员宅基地

文章浏览阅读267次。PyXLL是一款能够使得在Excel中能够执行Python脚本的插件,不过它是使用Excel扩展库(XLL)的方式,这跟平常加载一些常用的宏方式是一样的。使用pyXLL,首先你必须安装Python,目前支持2.X版本,你可以选择对应的版本下载:下载之后可能需要简单的配置,打开pyxll.cfg,在里面你可以设置你需要加载的模块,日志文件以存放路径等。里面还可以设置Licence,如果你有的话。(若..._excel trigger python 环境运行