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

c语言关键字(持续更新)

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

c语言关键字(持续更新)

目录
  • auto(自动变量)
  • register(寄存器)
  • extern(声明)
  • static
  • c语言基本数据类型
  • 变量名的命名规则
  • sizeof
  • signed、unsigned与整形在内存的存储
  • if else

auto(自动变量)

注:局部变量,自动变量,临时变量,都是一样的,统称局部变量。


c语言中auto关键字是用来修饰自动变量的,是C语言中应用最广泛的一种类型。
在程序内定义的局部变量,如果没有被声明为其他类型的局部变量都是自动变量。
可以得出结论:没有被auto修饰的局部变量都是自动变量。

//举例
#include 
auto int a = 0; //报错!全局变量不能被auto修饰
int main()
{
    for (int i = 0; i < 2; i++){
    printf("i=%dn", i);
    if(1)
   {
     auto int j = 0;  //自动变量
     printf("before: j=%dn", j);
     j += 1;
     printf("after : j=%dn", j);
   }
   return 0;
}


从运行结果可以看出:
(1)不管有没有被auto修饰的局部变量,都是自动变量!
(2)也就是说,如果i用auto修饰并且去掉j的auto都是没问题的。


结论:
(1)一般在代码块定义的变量,即局部变量,默认都是auto修饰的,一般都是省略的
(2)该关键字已经很老,基本永不使用
(3)全局变量不是自动变量,也不能用auto修饰


register(寄存器)

在电脑中CPU主要是负责进行计算的硬件单元,但是为了方便运算,一般第一步需要先把数据从内存读取到CPU内,

那么也就需要CPU具有一定的数据临时存储能力。注意:CPU并不是当前要计算了,才把特定数据读到CPU里面,那样太慢了。

所以现代CPU内,都集成了一组叫做寄存器的硬件,用来做临时数据的保存
距离CPU越近的存储硬件,速度越快


寄存器的作用
本质上可以提高计算机计算的效率,因为省略了去内存读取数据这一步骤!


register 修饰变量
建议:

  1. 局部变量可以存储到寄存器中(全局会导致CPU寄存器被长时间占用)
  2. 不会被写入内存的变量(写入就需要写回内存)
  3. 高频被读取的(提高效率)
  4. 现在的编译器,已经很智能了,能够进行比人更好的代码优化,不像早期编译器需要人为指定register,来进行手动优化。

#include 
int main()
{
   register int a = 0; //a变量被存储到寄存器中
   int* p = &a; //报错
   return 0;
}

报错的原因是:a已经被存储到寄存器中,不能被写入内存,因为地址是内存相关的概念!


extern(声明)

多文件

extern 声明变量
extern 声明函数
.c我们称之为源文件,一般包含函数实现,变量定义等
.h我们称之为头文件,一般包含函数声明,变量声明,宏定义,头文件等内容

//test.h
#pragma once //防止头文件被包含
#include  //c语言里面的头文件

extern int a; //声明变量,必须带上extern

extern void show(int n); //声明函数,建议带上extern

#define N 10 //宏定义
//main.c
#include "test.h" //""包含头文件,意思是包含自定义头文件

int main()
{
   show(200); //调用函数
   peintf("%dn",a); //输出变量
   return 0;
}
//test.c
#include "test.h" //意思跟上面一样

int a = 100; //对变量初始化

void show(int n) //函数的实现
{
   printf("hello %d worldn",n);
}

为什么要声明头文件(.h)
结论:因为组织项目结构的时候,减少大型项目维护的成本!


为什么头文件里要带上#pragma once?
结论:防止头文件被重复包含,导致程序运行效率变慢。


为什么变量声明必须带上extern?
结论:因为变量未初始化的时候,编译器会默认初始化为随机值或0。
注:声明变量是不需要开辟空间的,而定义变量并赋值是需要开辟空间的。


结论:
1.全局变量,是可以跨文件,被访问的。
2.全局函数,是可以跨文件,被访问的。
3. 所有变量声明必须带上extern
3.所有声明变量都不能初始化。
4.函数传参跨文件使用,建议在头文件声明函数和实现函数里写上参数。

注:在主函数外面定义或声明的都是全局变量。


static

想要了解static关键字的用法,请先移步到作用域和生命周期的文章c语言初识

static的作用
1.static修饰局部变量
局部变量生命周期变成全局变量生命周期,作用域不变。
2.static修饰全局变量
全局变量只能在本文件内使用。
3.static修饰函数
函数只能在本文件内使用,不能跨文件被访问(外部链接失效)。
注:static修饰全局变量影响的是作用域的概念,函数类似,生命周期不变。


static修饰局部变量

#include 

void test1()
{
   int a = 0; //局部变量
   a++;
 printf("No static = %d  ",a);
}

void test2()
{
   static a = 0; //static修饰的局部变量
   a++;
   printf("Yes static = %d  ",a);
}
int main()
{
   int i = 0;
   for(i = 0; i < 10; i++)
   {
      test1();
      putchar('n');
      test2();
   }
   return 0
   }


static修饰局部变量结论:

  1. 在函数体内定义局部变量具有临时性,函数结束,局部变量自动被释放。
  2. 被static修饰后的局部变量,被存储到静态区。
  3. 被static修饰的局部变量,具有全局生命周期性,出了代码块不会被释放,作用域不变,只能在代码块里定义的区域使用。

static修饰全局变量

//test.h
#include 
extern int a;
void fun(int num);
fun1();
//main.c
#include "test.h"
int main()
{
   printf("%dn",a); //报错,不能被外部文件直接访问
   fun(100); //报错,不能被外部文件直接访问
   fun1(); //通过间接访问的方式访问文件
   return 0;
}
//test.c
#include "test.h"
static int a = 200; //static修饰全局变量
static void fun(int num) //static修饰函数
{
   printf("%dn",num);
}
void fun1()
{
  fun(50);
}

全局变量可以跨文件使用吗?
可以!
函数可以跨文件使用吗?
可以!


结论:

  1. static修饰全局变量,该变量只能在本文件内使用,不能被外部其他文件直接访问。
  2. static修饰函数,该函数只能在本文件内使用,不能被外部其他文件直接访问。
  3. 可以通过间接访问的方式访问文件内部的变量和函数。

c语言基本数据类型

c语言内置类型如图所示:


c语言内置类型的本质是什么?
本质:在内存中开辟空间,用来存放数据。
但是定义一个变量,是需要类型的。那么,类型决定了:变量开辟空间的大小。

c语言类型32位系统(字节)64位系统(字节)
char11
short22
int44
long int44
long long int88
float44
double88
指针48

为什么要根据类型开辟空间?

  1. 因为开辟空间没有类型的话,就会造成不必要的浪费
  2. 一个工程里,都不是一个程序在运行,还有很多其他程序也在运行。如果我把空间一次性开辟完,其他程序就会没有空间存放数据了。
  3. 满足不同的计算场景。

最后如果有人还没没听懂的话,举个例子:
比如你跟朋友一起吃蛋糕,不是你自己一个人吃全部蛋糕,还有其他人在呢!另外,你自己吃整个蛋糕,一定能吃完吗?吃不完,就会造成浪费!所以说,要合理的分配蛋糕,不要贪吃。

注:蛋糕就是内存


变量名的命名规则
  1. 命名应当直观且可拼读,便于记忆与阅读。标识符采用英文单词或其组合,不允许使用拼音。
  2. 命名的长度合应符合:
    “minlength&&max+information”
    (最短长度,最大信息)
  3. 避免名字中出现数字编号,如a1,a2等。除非是逻辑上或驱动开发时需要。
  4. 程序中不得出现仅靠大小写区分的相似标识符。 例如:(int x and int X)
  5. 要特别注意1和l这一对的区别,还有0和o的区别,很多人容易搞混。
  6. 所有宏定义,枚举常量,标识符全都用大写英文命名,用下划线分割。
  7. 命名规范:英文字母(a-z,A-Z),数字(0-9),中间连接可用下划线(_)。

sizeof

有什么用?
sizeof是计算变量在内存中开辟空间的大小(单位:字节(byte))。


是函数吗?
sizeof是关键字不是函数。

//举例
#include 
int main()
{
   int a;
   printf("%dn"sizeof(int)); //4
   printf("%dn"sizeof(a));  //4
   printf("%dn"sizeof int); //报错
   printf("%dn"sizeof a); //4 
   //除了一个报错其他可以运行
   return 0;
}


结论:

  1. sizeof如果是函数的话sizeof a 就会报错,函数调用必须带括号。
  2. sizeof int报错原因是:不能同时存在二个关键字。

如何使用?

  1. sizeof在计算时,可是省略括号,但是括号内是数据类型就必须带上.
  2. sizeof在计算时,括号里面的变量最好不要进行运算,因为结果都是原来的值.
//举例
#include 
int main()
{
   int a = 0;
   printf("%dn", sizeof(a++)); //结果还是四个字节
   return 0;
}
  1. sizeof是在编译时求值,括号内进行运算是无效的.

signed、unsigned与整形在内存的存储

有符号类型 vs 无符号类型

有符号类型取值范围(32位平台)无符号类型取值范围(32位平台)
signed char[-128,127]unsigned char[0,255]
signed short[-32768,32767]unsigned short[0,65535]
signed int[-2147483648,2147483647]unsigned int[0,4294967295]
signed long[-2147483648,2147483647]unsigned long[0,4294967295]

通用有符号类型取值范围公式:[-2n-1,2n-1-1]
通用无符号类型取值范围公式:[0,2n-1]
注:n为比特位(bit)
=>>1字节(byte)== 8比特位(bit)


原反补码
计算机中的有符号数有三种表示方法,即原码、反码和补码。
原码:将十进制按照正负数的形式翻译成二进制。
反码:原码的基础上,符号位(第一位)不变,其余依次按位取反。
补码:反码的基础上+1。
如果一个数据是正数,那么它的原反补都相同!

//举例
#include 
int main()
{
   int a = 10; 
//原反补码:0000 0000 0000 0000 0000 0000 0000 1010 =>10的二进制
   printf("a=%dn", a);  //10
   unsigned int b = 10;
//原反补码:0000 0000 0000 0000 0000 0000 0000 1010 =>10的二进制
   printf("b=%un", b); //无符号类型输出 ==>10
   int c = -1;
//原码:1000 0000 0000 0000 0000 0000 0000 0001
//反码:1111 1111 1111 1111 1111 1111 1111 1110 =>符号位不变,其余取反
//补码:1111 1111 1111 1111 1111 1111 1111 1111 =>反码+1
   printf("c=%dn", c); //-1
   unsigned int d = -10;
//1000 0000 0000 0000 0000 0000 0000 1010
//1111 1111 1111 1111 1111 1111 1111 0101
//1111 1111 1111 1111 1111 1111 1111 0110
   printf("d(u)=%un", d); //4294967286
   printf("d(d)=%dn", d); //-10
   return 0;
}


为什么无符号输出unsigned int = -10的值等于429496…呢?

  1. 内存中开辟的空间里面存储的是-1的补码
  2. 无符号输出原反补码相等,不用转换为原码打印

为什么无符号类型可以存储负数?

  1. 内存中开辟的空间是用来存储数据的不管是正负数都可以存储,不要被类型给迷惑了
  2. 但是输出看类型!

注:

  1. 原码是十进制转二进制的概念
  2. 二进制第一位是符号位==>0表示“正”,1表示“负”
  3. 无符号数:不需要转化,也不需要符号位,原反补相同
    对于整形来说:数据存放内存中其实存放的是补码

补码转原码的方法:

  1. 补码-1,符号位不变,其余按位取反
  2. 原码到补码过程再实现一遍

十进制二进制快速转化

口诀:1后面跟n个0,就是2的n次方
例如:int a = 100;
二进制:26+25+22
0000 0000 0000 0000 0000 0000 0110 0100 ==>100
二进制快速转十进制也可以反过来用。
你学会了吗?


大小端
大端:高字节序存储到高权值位,低字节序存储到低权值位
小端:低字节序存储到高权值位,高字节序存储到低权值位


深入理解变量内容的存入和取出

//举例
#include 
int main()
{
   signed int a = -1;
   unsigned int b = -1; //会报错吗?
   //运行没有报错
   return 0;
}

结论

  1. 存:字面数据必须先转成补码,在放入空间当中。所以,所谓符号位,完全看数据本身是否携带±号。和变量是否有符号无关!
  2. 取:取数据一定要先看变量本身类型,然后才决定要不要看最高符号位。如果不需要,直接二进制转成十进制。如果需要,则需要转成原码,然后才能识别。(当然,最高符号位在哪里,又要明确大小端)

如何理解signed char = -128?
signed char 在内存中的分布

-128?
从补码的意义上去理解
256-128=128
所以,256+(-128)的补码=128
所以,(-128)的补码=256-128 =128
数学上,128 = 1000 0000
故而规定:-128的补码为 1000 0000


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

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

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