一. 初探指针数据类型
什么是指针?从根本上看,指针是一个值为内存地址的变量。正如 char 类型变量的值是字符,int 类型变量的值是整数,指针变量的值是地址。
- 声明指针变量:先指定指针所指向变量的类型,因为不同的变量类型占用不同的存储空间,然后跟一个 * 号,指定变量名。
int* int_pointer;
char* char_pointer;
- 赋值与初始化
// 赋值
int num_1 = 1;
int* int_pointer;
int_pointer = #
char a = 'a';
char* char_pointer;
char_pointer = &a;
double num_2 = 1.0;
double* double_pointer;
double_pointer = #
// & 为地址运算符,后跟一个变量时,给出该变量的地址
new 与 delete
new 与 delete 是 C++ 中的语法特性,与 C 语言中的 malloc 与 free 相对应,但功能更为强大,使用方便。因此我们只需学习 new 与 delete 即可。
new 与 delete 用来管理动态内存。new 在动态内存中为对象分配空间并返回一个指向该对象的指针,并且我们可以对该对象进行初始化
delete, 接受一个动态对象的指针,销毁该对象,并释放与之关联的内存
// 初始化, 就是在声明变量的时候为变量赋一个初始值
int* num_1 = new int{1} ;
delete num_1;
char* a = new char{'a'};
delete a;
double* num_2 = new double{1.0};
delete num_2;
动态内存的使用很容易出现问题,因为确保在正确的时间释放内存是及其困难的。
有时我们会忘记释放内存,在这种情况下就会产生内存泄漏
有时在尚有指针引用内存的情况下我们就释放了它,在这种情况下就会产生引用非法内存的指针
有时我们会重复释放同一块动态内存
- 打印指针 使用 %p 转换说明打印指针类型变量的值,即这个指针存储的地址。
int* num_1 = new int{1};
printf("%p\n" , num_1);
delete num_1;
char* a = new char{'a'};
printf("%p\n" , a);
delete a;
double* num_2 = new double{1.0};
printf("%p\n" , num_2);
delete num_2;
- 打印指针指向的内存空间里的值
使用地址运算符 *,后跟一个指针名时,* 给出存储在指针指向地址上的值
int* num_1 = new int{1};
printf("%d\n" , *num_1);
delete num_1;
char* a = new char{'a'};
printf("%c\n" , *a);
delete a;
double* num_2 = new double{1.0};
printf("%lf\n" , *num_2);
delete num_2;
C 程序的存储空间布局
Linux 操作系统下,每一个运行的程序(进程),操作系统都会为其分配一个 0 ~ 4G 的地址空间(虚拟地址空间)
二. Scanf 函数
这个函数用于输入,读取不同格式的数据。和 printf 函数一样,它也使用格式字符串和参数列表。
两个函数的区别在参数列表,printf 函数使用变量,常量和表达式。而 scanf 函数使用指向变量的指针
注意以下两条简单的规则:
- 如果用 scanf() 读取基本变量类型的值,在变量名前加上一个 &
- 如果用 scanf() 把字符串读入字符数组,不要使用 &
#include <stdio.h>
int main(void)
{
int num_1 = 0;
int num_2 = 0;
printf("Please input two numbers: ");
scanf("%d , %d" , &num_1 , &num_2);
printf("Sum: %d\n" , num_1 + num_2);
return 0;
}
三. const 限定符
const 关键字用于限定一个变量为只读。即可以使用、打印该变量,但是不能更改该变量的值
// 以下均不能编译通过
const int num = 1;
num = 2;
const char a = 'a';
a = 'b';
const double num_1 = 1.0;
num_2 = 2.0;
当我们想定义一个常量时,比如你的名字,你的生日,这是永远不会改变,我们就可以把这些数据定义为常量
四. 字符串
字符串是一个或多个字符的序列。双引号不是字符串的一部分,双引号仅告知编译器它括起来的是字符串,正如单引号 告知编译器它括起来的是字符一样。
C 语言中没有专门用于存储字符串的变量类型,字符串都被存储在 char 类型的数组中。
数组由连续的存储单元组成,字符串中的字符被存储在相邻的存储单元中,每个单元存储一个字符。注意数组末尾位置的字符 ‘\0’
‘\0’ 是空字符,C 语言用它标记字符串的结束。空字符不是数字 0,它是非打印字符,其 ASCII 码值是 0。计算机可以帮助你处理这个细节。
C 中的字符串一定以空字符结束,这意味着数组的容量必须比待存储字符串的字符数多 1
如何创建一个字符串呢?
#include <stdio.h>
int main(void)
{
const char praise[30] = {"You are an extraordinary being."};
char name[10] = {0};
printf("What's your name? ");
// 字符串的转换说明是 %s
scanf("%s" , name);
printf("Hello , %s. %s\n" , name , praise);
return 0;
}
字符串与字符
字符串常量 “x” 和字符常量 ‘x’ 不同。区别之一在于 ‘x’ 是基本类型(char),而 “x” 是派生类型(char 数组);区别之二是 “x” 实际上由两个字符组成:‘x’ 和空字符 \0
strlen 函数
#include <stdio.h>
#include <string.h>
int main(void)
{
const char praise[30] = {"You are an extraordinary being."};
char name[10] = {0};
printf("What's your name? ");
// 字符串的转换说明是 %s
scanf("%s" , name);
printf("Hello , %s. %s\n" , name , praise);
printf("Your name of %d letters occupies %ld memory cells\n" , strlen(name) , sizeof(name));
return 0;
}
作业
- 将讲义中的程序自己敲一遍,理解程序为何会这样运行