首页 > 其他分享 >1.常量与变量

1.常量与变量

时间:2023-06-29 17:13:36浏览次数:24  
标签:main 常量 int ++ func printf include 变量

1.常量

Def: 程序执行过程中值不会发生变化的量

(1)整型常量

1, 15, 6, etc

(2)实型常量

3.14, 5.6, etc

(3)字符常量

def:使用单引号引起来的单个字符或者转义字符

'j', '\n',
'\052'(表示八进制,注意后两位不能大于8),
'\x8f'(表示十六进制)

(4)字符串常量

def:使用双引号引起来的一个或多个字符形成的字符序列

"a", "abc\n\021\018"(表示字符"a" "b" "c" "\n" "\021" "\0" "1" "8"
"" 也是一个字符串——空串,只占用1byte

(5)标识常量#define

特点:处理在程序的预处理阶段,只占用编译时间,不占用运行时间,优点示一改全改,缺点是不检查语法正确与否。只是单纯的宏体与宏名之间的替换。

#define用法

  • 示例代码1
#include <stdio.h>
#include <stdlib.h>
//由于需要更改某个常量,而且该常量使用的次数很多,为了实现一改全改,使用define
#define PI 3.14  //we can change value to any one 
// define 宏名 + 宏体 
int main()
{
    int R, a, b;
    PI * 2 * R;
    a * PI;
    b * PI;
    exit(0);
}

预处理之后:

可见define 只是简单的对宏体进行宏名的替换。

  • 示例代码2:
#include <stdio.h>
#include <stdlib.h>

#define (ADD 2+3)

int mian()
{
    printf("%d\n",ADD * ADD);  //为表达准确,要加 ()
    
    exit(0);
}

预处理之后:

结果并不是(2+3)*(2+3)=25,而是等于2+3 * 2+3=11!
因此一定要注意使用不进行语法检查的define时,运算符的优先性。

  • 实例代码3:
#include <stdio.h>
#include <stdlib.h>

#define MAX(a,b) ((a) > (b) ? (a) : (b))  //宏名的宏体加(),变量加上()可以最大限度的避免因运算符可能造成的问题
int main()
{
    int i=5,j=3;
    printf("%d\n",MAX(i,j*2));
    
    exit(0);
}

预处理之后:

  • 示例代码3:
#include <stdio.h>
#include <stdlib.h>

#define MAX(a,b) ((a) > (b) ? (a) : (b)) 

int main()
{
    int i=5,j=3;
    printf("i = %d\t,j = %d\n", i, j );  //absolutely i=5, j=3
    printf("%d\n",MAX(i++,j++));   //due to i > j,and i was added twice
    printf("i=%d\t,j=%d\n",i,j);
    
    exit(0);
}

预处理之后:

结果:

Attention:使用宏与使用函数两者之间对比:

使用宏更节省整个编译时间,因宏处理过程只出现在预处理过程,不会出现在程序执行过程中。
针对内核层时,讲究实时性,一般多用define;针对应用层时,讲究稳定性,多用自定义函数。

如何解决上面出现的问题呢?使用一个变量接收 i++ and j++ 即可

Modified:

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

#define MAX(a,b) ({int A = a, B = b; (A) > (B) ? (A) : (B);}) 

int main()
{
    int i=5,j=3;
    printf("i = %d\t,j = %d\n", i, j );  //absolutely i=5, j=3
    printf("%d\n",MAX(i++,j++));   
    printf("i=%d\t,j=%d\n",i,j);
    
    exit(0);
}

Detailes:

printf("%d\n",MAX(i++,j++));
/*执行过程:
A = i++,B = j++;
MAX(i++,j++) ==> MAX(A, B) ==> (A) > (B) ? (A) : (B)*/

2.变量

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

[存储类型] 数据类型 标识符 = value(要与数据类型匹配)
TYPE NAME = VALUE

  • (1)标识符:定义的变量名;
  • (2)数据类型:基本数据类型+构造类型
  • (3)存储类型:auto(default) static register extern(说明型)
  • auto:默认类型,自动分配空间,自动释放空间。

    Example:
#include <stdio.h>
#include <stdlib.h>
//define a function
void func(void)
{
    /*auto*/int x = 0;
    x = x + 1;
    printf("%p -> %d\n",&x,x); //对x取地址操作,并输出a的值
}
int main()
{
    func();
    func();
    func();
    func();
}
  • 地址位置相同,但不同的编译器并不尽然,auto类型数据存储在栈上,内存分配是连续的,
  • 关于变量的生命周期与作用范围:变量x的调用是在函数func调用的时候发生的,函数结束时,该变量所占的内存空间被释放,因此下一次的x不是上一次的x
  • register:(建议性)寄存器类型。
  • 只能定义局部变量,不能定义全局变量;
  • 变量数据大小有限制,只能定义32位的数据类型,比如double就不可以;
  • 寄存器没有地址,因此一个寄存器类型的变量无法打印出地址查看和使用。
  • static:静态型,自动初始化为0值或者是空值,并且其变量的值具有继承性。常用于修饰变量或者函数,修饰变量时防止变量定义被重复调用,修饰函数时防止函数对外扩展。

Example:

#include <stdio.h>
#include <stdlib.h>
//define a function
void func(void)
{
    static int x = 0;  //func函数第一次被调用时,为该变量分配4byte(32bit)的内存并将其初始化为0,而第二次该函数func被调用的时候,由于第一次地址空间已经被定义过,第二次就不会再重新定义,直接跳过。由于其继承性,因此会出现第n次的值都会在第n-1的值的基础上加一。
    x = x + 1;
    printf("%p -> %d\n",&x,x); //对x取地址操作,并输出a的值
}
int main()
{
    func();
    func();
    func();
    func();
}
exit(0);
  • 输出值发生变化的原因在于:static只占用一个内存空间,亦即变量定义仅定义一次。
  • extern: 说明型,不能改变被说明的值或者类型。

1.变量的生命周期与作用范围

  • (1)全局变量与局部变量
  • (2)局部变量与局部变量

Example_1:

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

int i = 100;   //globle variable:作用范围到整个程序结束

int func(i)
{
    printf("i = %d\n",i);
}

int main()
{
    int i = 3;   //locale variable:作用范围在整个代码块结束
    func(i);
    {
        int i = 5;   //locale variable
        printf("i = %d\n",i);
    }
    exit (0);
}

Example_2:

//全局变量需要注意的地方
#include <stdio.h>
#include <stdlib.h>

int i=0;
void print_star(void)
{
    for(i = 0;i < 5;i++)  //调用该函数之后,i的值已经为5了,退出循环了;
    {
        printf("*");
    }
    printf("\n");
    printf("[%s]i = %d\n",__FUNCTION__ ,i);  //打印函数名中对应变量的值;
}

int main()
{
    for(i = 0;i < 5;i++)  //第一次调用函数之后i的值已经为5了
    {
        print_star();
    }
    printf("[s%]i = %d\n",__FUNCTION__ ,i);  //FUNCTION左右两边各两个"_"
    exit(0);
}

有关调试宏:

Result:

(3)参考

Project Example

建立main.c,proj.c,proj.h文件

  • main.c (main function)
#include <stdio.h>
#include <stdlib.h>
#include "proj.h"

int i = 10;
int main()
{
  printf("[%s]:i = %d\n",__FUNCTION__,i);
  func();
  exit(0);
}
  • proj.c (project function)
#include <stdio.h>
#include <stdlib.h>
#include "proj.h"

int i = 100;  //extern int i;此时输出结果均为为main.c中的值
void func(void)  // 返回值不需要传参(前者void),不需要传参(后者void)
{
   printf("[%s]:i = %d\n",__FUNCTION__,i);
   
   exit(0);
}
  • proj.h (project headfiles)
//为防止头文件被重复包含,需定义条件编译参数
#ifndef PROJ_H___  //如果未定义该宏
#define PROJ_H___  //就去定义它

void func(void);

#endif

Output:

/usr/bin/ld: /tmp/ccFbkDbY.o:(.data+0x0): multiple definition of `i'; /tmp/ccAyGFPM.o:(.data+0x0): first defined here
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
collect2: error: ld returned 1 exit status

++提示变量被多重定义。++

原因:main.cproj.c中的变量i均为auto类型,会被分配至同一个变量空间,因此会提示变量被重复定义。
修改:
main.c中:static int i = 10;proj.cstatic int i = 100;

Output:

[main]:i = 10
[func]:i = 100

注意:static修饰函数时防止函数对外扩展,被定义的函数只能被当前的代码块使用,使用extern则可以调用外部变量,其不可以修改变量值以及变量类型。

标签:main,常量,int,++,func,printf,include,变量
From: https://www.cnblogs.com/jxsme/p/17514673.html

相关文章

  • 02-ES6语法:const常量
    ES6标准中增加了新的关键字const来定义常量。使用const定义的常量,在后续的代码中将无法被改变。下面是简单的屏幕分享,不爱看文字的同道中人可以看视频。-_-一、基本常量首先我们来看下如何通过这个关键字定义常量,代码如下:<script>constPI=3.14159;console.info(PI)......
  • Java 中 BigDecimal 类型的变量的使用
    BigDecimal类的作用:Java的BigDecimal类用于进行高精度的十进制运算,避免了使用浮点数造成的精度丢失问题。 BigDecimal提供了许多方法来执行基本的数学运算,如加减乘除、比较、区域等。 BigDecimal类的常见用法示例:1、创建BigDecimal对象:BigDecimalnumber=......
  • 为什么在 C++ 中,类的静态成员变量需要在源文件中进行定义?
    为什么在C++中,类的静态成员变量需要在源文件中进行定义?类的静态成员变量需要在源文件中进行定义,以便在链接阶段能够正确地分配内存并为其分配地址。当你在类的头文件中声明一个静态成员变量时,这只是告诉编译器该变量存在,并将在某处定义。这是因为头文件通常被包含在多个源文件......
  • Java学习——变量和常量的相关知识
    变量inta=1,b=2,c=3;//不推荐Stringname="徐菲菲";charx='X';doublepi=3.14;变量作用域类变量(静态变量)定义在类中、方法之外的变量,并且使用static关键字修饰,作用域为整个类,可以被类中的任何方法、构造方法和语句块访问,静态变量的值在程序运行期间只有一个副本。......
  • 编程初学者入门5_键盘输入5个人的身高(米),求他们的平均身高(米)。(C的没问题,试着用Java写
    写在前面此系列博客为牛客网编程初学者入门题目小结,题目很基础不常用的知识容易遗忘,为了边复习c语言和学习Java,后面系列博客将采用c、c++、Java双语言版记录现在位置(72/140),虽然我走的很慢,但我仍在前进~题目描述从键盘输入5个人的身高(米),求他们的平均身高(米)。输入描述:一行,连续输......
  • 编程初学者入门7_公务员面试现场打分。有7位考官,从键盘输入若干组成绩,每组7个分数(百分
    题目描述公务员面试现场打分。有7位考官,从键盘输入若干组成绩,每组7个分数(百分制),去掉一个最高分和一个最低分,输出每组的平均成绩。输入描述:一行,输入7个整数(0~100),代表7个成绩,用空格分隔。输出描述:一行,输出去掉最高分和最低分的平均成绩,小数点后保留2位,每行输出后换行。示例1我的......
  • 网络安全学习篇37_第二阶段_基本Linux脚本、变量、判断if、循环for\while、case语句
    上一篇博客:网络安全学习篇36_第二阶段_简单介绍JavaWeb框架之Tomcat服务、Nginx负载均衡、Linux包过滤防火墙IPtables、NAT网络地址转换目录shell脚本变量数值读入if判断语句for、while循环语句case语句开始shell脚本1.脚本的作用:可以执行计划任务把需要执行的代码保存在一个文件......
  • jmeter中跨线程调用变量
    Jmeter中跨线程调用变量一.Jmeter中线程运行规则1.各个线程组是完全独立的,每个线程组是不同的业务,互不影响2.线程组中的每个线程也是完全独立3.线程组中的每个线程,都是从上往下执行,完成一轮循环后,继续下一轮循环4.存在业务流或者接口之前存在依赖关系的放同一个线程组5.setup......
  • 获取或者设置AutoCAD的变量
    1、通用做法,可以通过acedGetVar(constACHAR*sym,structresbuf*result);函数来获取变量,通过acedSetVar()函数来设置变量2、如果是某些数据库AcDbDatabase相关变量,可以通过下面示例获取变量Adesk::Int16pdmode=acdbHostApplicationServices()->workingDatabase()->pdmode......
  • PHP 常量的说明和使用
    常量类似变量,但是常量一旦被定义就无法更改或撤销定义。PHP常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有$符号)。注释:与变量不同,常量贯穿整个脚本是自动全局的。设置PHP常量如需设置常量,请使用define()函数-它使......