概念
在程序运行的过程中,不可以改变的值称为常量。
1.常量的分类
1. 整形常量
程序常量书写格式:十进制,八进制,十六进制,二进制
举例:1314 0520 0xFFFF 0b10011000
整形常量默认都是int类型,因此在内存中占用4字节的空间。
举例:1314U 0520U 0xFFFFU 0b10011000U
在整形常量后边加一个字符U,表示整形常量为unsigned int类型,
因此在内存中占用4字节的空间。
#include <stdio.h>
int main(int argc, const char *argv[])
{
// %d : 有符号整型的格式化字符
// %u : 无符号整型的格式化字符
// %ld : 有符号长整型的格式化字符
// %lu : 无符号长整型的格式化字符
// %o : 无符号整数的8进制输出格式化字符
// %x : 无符号整数的16进制输出格式化字符
printf("1314有符号的整型常量=%d, 有符号整型常量占用内存大小 = %ld\n",
1314, sizeof(1314));
printf("0x1314有符号的整型常量=%#x, 有符号整型常量占用内存大小 = %ld\n",
0x1314, sizeof(0x1314));
printf("0567U无符号的整型常量=%#o, 无符号正常常量占用内存大小 = %ld\n",
0567, sizeof(0567));
return 0;
}
2. 实型常量(浮点型常量)
一般书写格式:3.1415926
科学计数格式:
举例:
3.14e+2 ---> 3.14 * 10^2
3.14e-2 ---> 3.14 * 10^-2
浮点型常量默认为double类型,因此在内存中占用8字节的空间。
#include <stdio.h>
int main(int argc, const char *argv[])
{
// %f : float类型的格式化输出字符
// %lf : double类型的格式化输出字符
// %e : float类型的格式化输出字符,以科学计数方式输出
// %le : double类型的格式化输出字符,以科学计数方式输出
// 一般格式浮点型常量
printf("3.14浮点型常量 = %lf, 3.14浮点型常量占用内存的大小 = %ld\n",
3.14, sizeof(3.15));
printf("3.1415e3浮点型常量 = %le, 3.1415e3浮点型常量占用内存的大小 = %ld\n",
3.1415e3, sizeof(3.1415e3));
printf("3.1415e3浮点型常量 = %lf, 3.1415e3浮点型常量占用内存的大小 = %ld\n",
3.1415e3, sizeof(3.1415e3));
printf("3141.5浮点型常量 = %le, 3141.5浮点型常量占用内存的大小 = %ld\n",
3141.5, sizeof(3141.5));
return 0;
}
3. 字符常量
字符常量必须使用''单引号括起来。
举例:'A' 'a' '9' '\n' '\0' .....
'aa' ----> 书写格式错误
字符型常量默认为char类型,因此在内存中占用1字节的空间。
#include <stdio.h>
int main(int argc, const char *argv[])
{
// sizeof在计算字符'A'变量占用内存空间大小时,
// 本质上计算的时字符'A'的ASCII码值占用的内存空间大小,
// sizeof将字符'A'的ASCII码值65当成一个有符号的整数计算。
printf("A字符 = %c, A字符的大小 = %ld\n", 'A', sizeof('A'));
// 等价于以下写法:
printf("A字符 = %c, A字符的大小 = %ld\n", 'A', sizeof(65));
// 因此要计算字符常量的大小,需要定义字符类型的变量
char ch = 'A'; // 给变量ch赋值字符常量'A'
printf("A字符 = %c, A字符的大小 = %ld\n", 'A', sizeof(ch));
return 0;
}
4. 字符串常量
字符串常量必须使用""双引号括起来,字符串的结尾默认有一个'\0'.
举例:"hello" "nihao" "a" .....
#include <stdio.h>
int main(int argc, const char *argv[])
{
// sizeof在计算字符'A'变量占用内存空间大小时,
// 本质上计算的时字符'A'的ASCII码值占用的内存空间大小,
// sizeof将字符'A'的ASCII码值65当成一个有符号的整数计算。
printf("A字符 = %c, A字符的大小 = %ld\n", 'A', sizeof('A'));
// 等价于以下写法:
printf("A字符 = %c, A字符的大小 = %ld\n", 'A', sizeof(65));
// 因此要计算字符常量的大小,需要定义字符类型的变量
char ch = 'A'; // 给变量ch赋值字符常量'A'
printf("A字符 = %c, A字符的大小 = %ld\n", 'A', sizeof(ch));
return 0;
}
5. 标识常量(宏定义)
宏定义的语法格式:
#define 宏定义名 宏定义的值
宏定义名:
1> 宏定义的名一般为大写,也可以是小写
宏定义的值:
1> 使用宏定义的名表示宏定义的值
注:
1> 宏定义就是在预处理阶段进行傻瓜式替换,
使用宏定义的值直接替换宏定义的名。
2> 宏定义结尾不可以有分号,默认一条宏定义占1行,
如果宏定义要分成多行进行书写,必须在结尾加续行符"\"
3> 如果宏定义的值是一个数学表达式,尽量根据运算的优先级加().
#include <stdio.h>
// 宏定义一般定义到main函数上边
#define PI 3.14
#define INTEGER 12345678
#define STRING "hello world"
#define CH 'Z'
int main(int argc, const char *argv[])
{
// 宏定义在预处理阶段进行简单替换
printf("PI = %lf\n", PI);
printf("INTEGER = %d\n", INTEGER);
printf("STRING = %s\n", STRING);
printf("CH = %c\n", CH);
return 0;
}
执行:gcc -E 10define.c -o 10define.i ---> 预处理的命令
cat回显一下文件内容
796 int main(int argc, const char *argv[])
797 {
798
799 printf("PI = %lf\n", 3.14);
800 printf("INTEGER = %d\n", 12345678);
801 printf("STRING = %s\n", "hello world");
802 printf("CH = %c\n", 'Z');
803 return 0;
804 }
2.宏定义的值有算数表达式
#include <stdio.h>
// 在宏定义的值中如果使用了复杂的算数表达式,尽量多加(),提升运算的优先级
#define ADD 10 + 20
#define SUB (100 - 20)
int main(int argc, const char *argv[])
{
printf("result = %d\n", ADD * 5); // 110
// 替换之后的结果:printf("result = %d\n", 10 + 20 * 5); //
printf("result = %d\n", SUB * 5); // 400
// 替换之后的结果:printf("result = %d\n", (100 - 20) * 5);
return 0;
}
3.带参数的宏定义
#include <stdio.h>
#define PI (3.14)
#define D(r) (2 * r)
// 定义一个宏,求矩形的周长
#define RECT_PER(w, h) (2 * (w + h))
int main(int argc, const char *argv[])
{
// 求圆的周长
printf("圆的周长 = %lf\n", PI * D(5)); // 给宏定义传递的参数会替换宏定义的参数符号
printf("矩形的周长 = %d\n", RECT_PER(5,4));
return 0;
}
4.宏定义跟单个#结合使用
在参数前加 # 之后,在替换过程中会自动在s对应的参数两边加 " "
#define STR2(s) #s
#include <stdio.h>
#define STRING "hello world"
#define STR1(s) s
// 在参数前加#号之后,会替换的过程中会自动在s对应的参数两边加""
#define STR2(s) #s
int main(int argc, const char *argv[])
{
printf("STRING = %s\n", STRING);
// ---> 替换之后结果 printf("STRING = %s\n", "hello world");
// printf("STR1(hello) = %s\n", STR1(hello)); ---> 编译报错
// ---> 替换之后的结果 printf("STR1(hello) = %s\n", hello);
printf("STR1(\"hello\") = %s\n", STR1("hello"));
// ---> 替换之后的结果 printf("STR1("hello") = %s\n", "hello");
printf("STR2(hello) = %s\n", STR2(hello));
return 0;
}
5.宏定义跟俩个 ## 使用
可以实现两个字符串的拼接
#include <stdio.h>
#define PRINT pri##ntf("hello world!\n")
#define myuint64_t unsigned long
#define myuint32_t unsigned int
#define myuint16_t unsigned short
#define myType(size) myuint##size##_t
int main(int argc, const char *argv[])
{
PRINT;
// 替换之后的结果:printf("hello world!\n");
myuint32_t a; // 替换之后结果:unsigned int a;
myType(32) b;
// 替换结果:myuint32_t ---> unsigned int
return 0;
}