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,常量,int,++,func,printf,include,变量 From: https://www.cnblogs.com/jxsme/p/17514673.html原因:
main.c
与proj.c
中的变量i
均为auto
类型,会被分配至同一个变量空间,因此会提示变量被重复定义。
修改:
main.c
中:static int i = 10
;proj.c
中static int i = 100
;
Output:[main]:i = 10 [func]:i = 100
注意:
static
修饰函数时防止函数对外扩展,被定义的函数只能被当前的代码块使用,使用extern
则可以调用外部变量,其不可以修改变量值以及变量类型。