国嵌C语言总结(1-5)

article/2025/11/6 0:42:30

国嵌一:

什么是数据类型?

        数据类型是固定内存大小的别名,是创建变量的模子;

变量的本质?

  • 变量是一段实际连续存储空间的别名;
  • 程序通过变量来申请并命名存储空间;
  • 通过变量的名字可以使用存储空间。

Linux命令行:gcc.test.c 编译     ./a.out 运行

数据类型:

  • 自定义类型:typedef定义类型
  • 创建变量:TYPE,name
  • 通过打印语句证明本质:printf
#include <stdio.h>
int main(void)
{char c=0;short s=0;int i=0;printf("%d,%d\n",sizeof(char),sizeof(c));printf("%d,%d\n",sizeof(short),sizeof(s));printf("%d,%d\n",sizeof(int),sizeof(i));
}1,1
2,2
4,4typedef int INT32;
typedef unsigned char BYTE;
typedef struct _demo{short s;BYTE b1;BYTE b2;INT32 i;
}DEMO;int main(void)
{INT32 i32;BYTE byte;DEMO d;printf("%d,%d\n",sizeof(INT32),sizeof(i32));printf("%d,%d\n",sizeof(BYTE),sizeof(byte));printf("%d,%d\n",sizeof(DEMO),sizeof(d));}4,4
1,1
8,8

国嵌二:

        auto为C语言局部变量的默认属性,编译器默认所有的局部变量都是auto,在栈上分配内存;

         register指明将变量存储在寄存器中,只是请求寄存器变量,但是不一定成功;需要的目的是:由于从寄存器中取值比内存中快的多,因此可以应用到讲究性能的实时系统中。特别是函数经常被调用时;register的变量必须是CPU寄存器可以接受的值,不能用&运算符获取变量的地址。

        static指明变量的静态属性,同时具有作用域限定符的意义;修饰的局部变量存储在程序的静态工作区;static还可以作为文件作用域标识符,即修饰的全局变量的作用域只是在声明的文件中,修饰的函数作用域只是声明的文件之中。局部变量的生命中周期是函数的运算期,但是static修饰的局部变量是整个生命周期。

补充:

        auto 存储类是所有局部变量默认的存储类,auto 只能用在函数内。

        register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。定义 'register' 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

        static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。

        extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 'extern' 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。当有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。

#include <stdio.h>
int main()
{auto int i = 0;register int j = 0;static int k = 0;    return 0;
}

4,4

1,1

8,8

#include <stdio.h>
int g=0;
int m=0;
void f1()
{int i=0;i++;printf("%d,",i);                //局部变量,退出后释放
}
void f2()
{static i=0;                    //静态局部变量,初始化一次,不释放i++;printf("%d,",i);
}
int main()
{auto int i = 0;register int j = 0;static int k = 0;printf("%0x\n",&i);//printf("%0x\n",&j);         //要求寄存器变量j的地址printf("%0x\n",&k);for(i=0;i<5;i++){f1();                    //在栈上占用空间,每次运行完就释放}printf("\n");for(i=0;i<5;i++){f2();           //在静态存储区占用空间,只会被初始化一次,每次运行完后保留上一次的值}return 0;
}

1,1,1,1,1

1,2,3,4,5

  • //auto int g=0;//错误,文件作用域中g的声明指定了auto
  • //register int m=0;//m的寄存器名无效,全局变量不可能是寄存器变量

另一个文件如果是int test_g=1;则可以打印test_g得值;

int test_f1()
{return test_fun();
}

如果是static int test_g=1;则不可以打印test_g得值

static int test_g=1;
int test_fun()
{return test_g;
}

如果是static int test_fun()则不可以打印test_g得值,如果再加一个函数,可以打印test_g得值。

  •  外部变量和静态变量由编译程序给予隐含的初始值0;
  • 局部变量的初始化每进入函数便初始化一次。
  • 外部或静态变量仅在编译时初始化一次。
  • 自动变量或寄存器变量只能显示初始化,否则将有不确定的值。
  • 外部数据的说明,如果带有初始化项,则当成一个定义。

        auto 普通局部栈变量,是自动存储,这种对象会自动创建和销毁 ,建议这个变量要放在堆栈上面,调用函数时分配内存,函数结束时释放内存。一般隐藏auto默认为自动存储类别。我们程序都变量大多是自动变量。

#include <stdio.h>
int main(void) 
{ auto int i = 9; /* 声明局部变量的关键字是 auto; 因可以省略, 几乎没人使用 */ printf("%d\n", i); getchar(); return 0; 
}

        Register变量:动态和静态变量都是存放在内存中,程序中遇到该值时用控制器发指令将变量的值送到运算器中,需要存数再保存到内存中。如果频繁使用一个变量,比如一个函数体内的多次循环每次都引用该局部变量,我们则可以把局部变量的值放到CPU的寄存器中,叫寄存器变量。不需要多次到内存中存取提高效率。但是只能局部自动变量和形参可以做寄存器变量。在函数调用时占用一些寄存器,函数结束时释放。不同系统对register要求也不一样,比如对定义register变量个数,数据类型等限制,有的默认为自动变量处理。所以在程序一般也不用。

#include <stdio.h>
#include <>
#define TIME 1000000000 
int m, n = TIME; /* 全局变量 */ 
int main(void) 
{ time_t start, stop; register int a, b = TIME; /* 寄存器变量 */ int x, y = TIME; /* 一般变量 */ time(&start); for (a = 0; a b; a++); time(&stop); printf("寄存器变量用时: %ld 秒\n", stop - start); time(&start); for (x = 0; x y; x++); time(&stop); printf("一般变量用时: %ld 秒\n", stop - start); time(&start); for (m = 0; m n; m++); time(&stop); printf("全局变量用时: %ld 秒\n", stop - start); return 0; 
}

输出结果:寄存器变量用时: 1 秒 一般变量用时: 8 秒 全局变量用时: 9 秒

static 可以用来修饰局部变量,全局变量以及函数。在不同的情况下 static 的作用不尽相同。

(1)修饰局部变量

#include void fun() 
{ static int a=1; a++; printf("%d\n",a); 
} 
int main(void) 
{ fun(); fun(); return 0; 
}

程序执行结果为: 2 3

(2)修饰全局变量

//有file1.c 
int a=1; 
file2.c 
#include <stdio.h>
extern int a; 
int main(void) 
{ printf("%d\",a); return 0; 
}

则执行结果为 1

但是如果在 file1.c 中把 int a=1 改为 static int a=1;那么在file2.c是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。

(3)修饰函数

        用static修饰函数的话,情况与修饰全局变量大同小异,就是改变了函数的作用域。

国嵌三:

if语句需要注意:

  • bool型变量应该直接出现在条件中,不能进行比较;
  • 普通变量和0值比较时,0值应该出现在比较符号的左边,防止出现赋值的情况;
  • float型变量不能直接进行0值比较,需要定义精度;

         在输入时:使用非零值表示真;零值表示假。在输出时:真的结果是1,假的结果是0。当在一个需要布尔值的地方,也就是其它类型转化为布尔类型时,比如 if 条件判断中的的条件;“输出”的意思是:程序的逻辑表达式返回的结果,也就是布尔类型转化为其他类型时,比如 a==b的返回结果,只有0和1两种可能。

 switch语句需要注意:

  • switch语句对应单个条件多个分值的情况,
  • 每个case语句必须要有break,否则会出现分支重叠;
  • case语句中的值只能是整形或者字符型。

if语句可以安全从功能上替代switch语句,但是switch语句无法替代if语句。

void f1(int i)
{if( i < 6 ){printf("Failed!\n");}else if((6<i)&&(i<=8))//范围的话switch无法替代if{printf("Good!\n");}else{printf("Perfect!\n");}
}
void f2(char i)
{switch(i){case 'c':printf("Compile\n");break;case 'd':printf("Debug\n");break;case 'o':printf("Object\n");break;case 'r':printf("Run\n");break;default:printf("Unknown\n");break;}
}
int main()
{f1(5);f1(9);f2('o');f2('d');f2('e');
}

failed  prefect  object  debug  unknown

循环语句分析:

  • do语句先执行后判断,循环体至少执行一次;
  • while语句先判断后执行,循环体可能不执行;
  • for语句先判断后执行,相比于while更简便;
#include <stdo.h>
int f1(int n)
{int ret = 0;int i = 0;for(i=1; i<=n;i++){ret += i;}return ret;
}
int f2(int n)
{int ret = 0;while( (n > 0) && (ret += n--) );return ret;
}
int f3(int n)
{int ret = 0;if( n > 0 ){do//至少执行一次{ret += n--;}while( n );}return ret;
}
int main()
{printf("%d\n", f1(10));printf("%d\n", f2(10));printf("%d\n", f3(10));
}

55 55 55

  • break语句是跳出循环;
  • continue语句是跳出本次循环,进入下次循环;
  • switch语句不能使用continue,因为switch语句本身不存在循环。
#include <stdio.h>
int func(int n)
{int i = 0;int ret = 0;int* p = (int*)malloc(sizeof(int) * n);//分配动态内存do{if( NULL == p ) break;                //不能用return 0;如果返回值不是0,会出现内存错误if( n < 0 ) break;                //不能用return 0;如果返回值不是0,会出现内存错误for(i=0; i<n;i++){p[i] = i;printf("%d,", p[i]);}ret = 1;}while(0);free(p);                    //释放内存return ret;
}
int main()
{if( func(10) ){printf("OK");}else{printf("ERROR");}
}

0,1,2,3,4,5,6,7,8,9 OK

国嵌四:

goto禁用。

goto虽好不使用,因为它使得程序的控制流难以跟踪,使程序难以理解和难以修改。:

#include <stdio.h>
void func(int n)
{int* p = NULL;if( n < 0 ){goto STATUS;}p = malloc(sizeof(int) * n);STATUS:p[0] = n;
}
int main()
{f(1);f(-1);return 0;
}

void的意义

        C语言没有定义void究竟是多大的内存的别名,无法在内存中裁剪出void对应的变量。如果函数没有返回值,没有参数,就应该声明为void型;且在C语言中void不占据内存。

void*指针应该注意的问题:

  • 在C语言中只有相同类型的指针才可以进行相互赋值;
  • void*指针作为左值用于接收任意类型的指针;
  • void*作为右值赋值给其他指针,需要强制类型的转换。

void* my_memset(void* p,char v,int size)
{void* ret=p;char* dest=(char*)p;int i=0;for(i=0;i<size;i++){dest[i]=v;}return 0;
}
int main()
{int a[5]={1,2,3,4,5};int i=0;for(i=0;i<5;i++){printf("%d,",a[i]);}printf("\n");my_memset(a,0,sizeof(a));for(i=0;i<5;i++){printf("%d,",a[i]);}return 0;
}

1,2,3,4,5

0,0,0,0,0

extern 中隐藏的意义:

  • extern用于声明外部定义的变量和函数,
  • extern告诉编译器用C语言的方式编译。

(由于c++编译器和一些其他编译器会按照自己的编译方式运行,而通过extern可以命令编译器以标准的C语言方式进行编译)

test.c
/*
extern "C"
{int add(int a, int b){return a + b;}
}
*/
extern int g;
extern int get_min(int a, int b);
int main()
{printf("%d\n",g);printf("%d\n",get_min(1,5));return 0;
}
// test2.c
int g = 100;
int get_min(int a, int b)
{return (a < b) ? a : b;
}

gcc test.c test2.c        ./a.out

100,1

sizeof不是函数:

  • sizeof是编译器的内置指示符,不是函数,
  • sizeof用于计算相应实体所占据的内存大小;
  • sizeof的值在编译期就已经确定了
int main()
{int a;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);//充分证明sizeof不是函数printf("%d\n", sizeof(int));return 0;
}

4,4,4

国嵌五:

const修饰变量:

  • const修饰的变量是只读的,其本质还是变量,
  • const会占据一定的内存空间;
  • 本质上const只对编译器有用,在运行时无用;
int main(void)
{const int cc=1;printf("%d\n",cc);cc=3;            //只读类型,不能修改,故报错printf("%d\n",cc);
}
int main(void)
{const int cc=1;int *p=(int *)&cc;printf("%d\n",cc);*p=3;printf("%d\n",cc);}

1,3

const修饰数组:

  • const修饰的数组是只读的;
  • const修饰的数组空间不可被改变,通过指针可以更改。

const修饰指针:(左数右指)

  • 当const出现在*左边的时候,指针指向的数据为常量,
  • 当const出现在*右边的时候,指针本身为常量。
  • const int *p; //p可变,p指向的内容不可变;
  • int const *p; //p可变,p指向的内容不可变;
  • int *const p; //p不可变,p指向的内容可变;
  • const int *const p; //p和p指向的内容都不可变;
#include <stdio.h>
int main(void)
{int i=0;//const int *p=&i;//*p=3; //只读,不能改变,报错//int const*p=&i;//*p=3; //同上int* const p=&i;*p=3; //编译通过//int* const p=&i;//p=NULL; //只读,不能改变,报错//const int* const p=&i;//*p=3; //同上//p=NULL; //同上
}

const修饰函数参数和返回值:

  • const修饰函数表示在函数体内不希望改变参数的值。
  • const修饰函数返回值表示返回值不可改变,多用于返回指针的情形。
#include <stdio.h>
const int* func()
{static int count=0;count++;return &count;
}
int main(void)
{int i=0;const int* p=func();//没有const就会有警告,因为返回的地址是不可改变的printf("%d\n",*p);
}

1

volatile的理解:

  • volatile可以理解为编译器警告指示字,
  • volatile用于告诉编译器必须每次去内存中取变量的值;
  • volatile主要修饰被多个线程访问的变量,
  • volatile也可以修饰可能被未知因数更改的变量。

         const和volatile是可以同时修饰一个变量的  const只是表示变量只读 不能出现在赋值号左边  防止程序“意外”修改   并且编译器一定会做优化 不会每次去内存取值 这个时候如果外部事件 如中断服务程序 改了这个变量的内存值  那么由于编译器优化就不会出有反应 这样会导致错误 加上volatile就告诉编译器 不要做任何优化  并且每次都去内存取值  而且这个变量不可以当左值使用 .

问题1:const与volatile是否可以修饰同一个变量?

        如果一个变量不会被本程序改变,通常可能给它加上const,但如果该变量可能被其他程序改变而本程序又在检测这个变量的值,就需要给它加上volatile,于是变量就同时有volatile和const了,这个时候i具有const和volatile的双重属性。

 问题2:const volatile int i=0;这个是时候i具有什么属性?编译器如何处理这个变量?

        i变量不可以在编译过程中被程序代码修改,同时编译器不得对i进行优化编译。


http://chatgpt.dhexx.cn/article/9hPpWVvW.shtml

相关文章

使用新版IDEA创建JavaWeb项目详细图文教程

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 示例概述 三月中下旬了&#xff0c;答辩的日子也越来越近了。之前忙于考研的童鞋&#xff0c;之前忙着玩的童鞋&#xff0c;之前忘记做毕业设计的童鞋都开始忙碌起来了。奈…

idea2022创建javaweb项目

idea版本2022 1.2 //记录一下javaweb的创建 ​​​​​​ name项目名称 location存储地址 Application server&#xff1a;选择new 选中Tomact service 点击下一步 点击下一步就创建成功了

idea创建一个javaweb项目

前提 java环境以及tomcat的安装 1、IDEA创建Web项目 此处以Idea 2020.3.4举例 1、新建普通Java项目 注意&#xff1a;Idea2020无法直接新建JavaWeb项目&#xff0c;只能通过新建普通Java项目的方式间接新建JavaWeb项目。 选择项目位置和普通Java项目相同&#xff0c;此处略过…

java web项目_一个完整JavaWeb项目开发总结

一个JavaWeb项目开发总结 曾经&#xff0c;我跟朋友说我要去学Java&#xff0c;到现在1个月&#xff0c;我总算是七拼八凑的写出了我人生中的第一个Javaweb项目&#xff0c;虽然只是一次简单的爬虫&#xff0c;但是却也更坚定了我学Java的决心 就手写一份我做这次Javaweb项目得…

Linux服务器部署JavaWeb项目

目录 1.搭建JavaWeb环境1.1 安装Java环境1.2 安装 MySQL1.2.1 下载并安装 MySQL1.2.2 启动 MySQL 服务1.2.3 查看 MySQL 默认密码1.2.4 登录 MySQL1.2.5 修改密码1.2.6 为root赋值远程管理权限1.2.7 退出服务器测试 MySQL 连接1.3 安装 Tomcat 2.部署JavaWeb项目2.1 将项目打包…

javaweb项目的文件结构

javaweb项目的文件结构 1、前言 最近使用Intellij idea搭建一个springmvc的web项目时&#xff0c;突然发现&#xff0c;自己好像对web项目的文件结构不是很清晰&#xff0c;对于项目中应该有那些文件夹、文件夹里面又是怎么的文件、他们的作用又是什么&#xff1f;这些好像有点…

JavaWeb项目打包运行

简单记录下JavaWeb项目打包运行 文章目录 项目打包tomcat运行项目 一、项目打包 1.选择out输入目录路径 这里我们可以新建一个文件夹 然后选择 项目打包完就在这个目录底下 2.创建一个工件 3.这里的Name默认的是unnamed 这个 我们这里修改成项目名称 先选择output ro…

JavaWeb项目的热部署配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 热部署概述 我们通常期望&#xff1a;修改页面和Java代码后不用重新手动部署项目就可即刻生效&#xff1b;这就是最理想的热部署。然而&#xff1b;理想有多丰满&#xff0…

161个Javaweb项目免费

161个javaweb’项目加qq群&#xff08;105613691&#xff09;自取。网上一些假货我当时找半天找不到费事而且贼生气。现在分享出 如下 <% page language"java" pageEncoding"utf-8"%> <%String path request.getContextPath();String basePat…

JavaWeb项目结构使用Vue项目

提示&#xff1a;javaweb项目中引用Vue项目的案例 文章目录 前言一、JavaWeb项目结构项目启动顺序 二、Vue项目结构Vue结构粗略解释思考 三、使用Vue1、使用vue.js, 在html引用2、使用webpack 构建Vue脚手架第一步&#xff1a; 到webapp包下&#xff0c;输入命令 npm init -y第…

JavaWeb项目结构

4.1 web结构 必需严格按照一种规范来完成 咱们要开发Javaweb的程序,必需要严格参照javaweb提供的一个规范来存放我们的资源…… 结果分析如下: 注意:WEB-INF里面的程序是不可见的,必需通过我们的程序访问 现在:web.xml都不是必需的(但是我们要求必需留着)–这个web.xml可…

eclipse部署Javaweb项目

目录 0.安装Tomcat1.配置Eclipse项目的Tomcat Server2.导入Java Web项目3.设置Tomcat4.配置数据库5.运行项目 0.安装Tomcat 请自行百度搜索如何安装Tomcat&#xff0c;每个项目对Tomcat的版本要求不同&#xff0c;安装之前自行查询你的项目所需要的Tomcat版本。 1.配置Eclips…

linux 部署Javaweb项目

目录 一、配置Java环境1.正确开启linux镜像服务器 二、配置MySQL环境 三、运行Java项目1.在/opt/soft目录下找到apache-tomcat-8.5.81.tar.gz文件并解压 一、配置Java环境 1.正确开启linux镜像服务器 2.正确通过xshell工具链接linux镜像服务器 ip a 3.关闭防火墙 systemct…

IDEA 导入别人的javaweb项目进行部署

前言 我主要是进行java的springboot项目和vue项目的开发&#xff0c;但是架不住在这些框架兴起之前&#xff0c;公司内部已经是有其他的老的框架&#xff0c;我需要在这些老的框架进行修改和调整代码。原本我是使用的eclipse软件进行部署&#xff0c;也比较简单&#xff1b; …

eclipse导入javaWeb项目

eclipse如何正确导入web项目&#xff0c;参考视频&#xff1a;https://www.bilibili.com/video/BV1tV411x7Fb?spm_id_from333.337.search-card.all.click&vd_source825d3d7ea7fd6488824d9e1ce89f8716 二、我遇到的问题 Target runtime Apache Tomcat v7.0 is …

Javaweb项目报告

项目名称&#xff1a;学生考勤系统 主要功能&#xff1a;添加、删除、修改、查询 数据库字段&#xff1a; DROP DATABASE IF EXISTS AttDB; CREATE DATABASE AttDB CHARACTER SET utf8; USE AttDB;CREATE TABLE Student(sid INT PRIMARY KEY AUTO_INCREMENT COMMENT 学号,sn…

javaweb项目搭建

JavaWeb项目搭建 1.新建一个java项目 2.让这个java项目成为web项目 3.导入项目所需依赖 在WEB-INF下新建lib目录存放jar包&#xff0c;并添加到环境中 4.连接数据库 新建一个连接数据库的类 url“jdbc:mysql://localhost:3306/db1?serverTimezoneAsia/Shanghai&useUnic…

javaweb项目

源码&#xff1a;&#xff08;百度网盘&#xff09; 链接&#xff1a;JavaWeb 提取码&#xff1a;3xf9 链接: Oracle数据库文件 提取码&#xff1a;vkko 说明&#xff1a; 不希望大家复制粘贴、交作业&#xff0c;一气呵成&#xff0c;动作行云流水。而是希望看下面的讲解&am…

JavaWeb项目开发步骤

JavaWeb项目开发步骤 前言&#xff1a;跟着视频学习搭建实现smbms超市管理系统&#xff0c;学习到了很多关于项目实现的一些东西&#xff0c;这里关于javaWeb的smbms进行项目跟着做一遍后的感受&#xff0c;主要讲的是整体感观&#xff0c;记录学习以及发布分享 一、项目需求…

创建JavaWeb简单项目(超级详细、一看就会)—— 1

在编写我们这个简单的JavaWeb项目之前&#xff0c;我先来介绍一下本项目的项目环境。 本项目是基于JavaWeb的开发环境&#xff0c;具体使用了以下技术和工具&#xff1a; JavaWeb&#xff1a;JavaWeb是Java平台上的Web开发技术&#xff0c;它包括了Servlet、JSP、JavaBean、JD…