1. 变量分成三种:全局变量,局部变量和块变量
变量的作用域指的是“变量名“的作用域,而非变量;生命周期和作用域一致;
变量和变量名是不一样的;
全局变量在程序开始前就默认初始化为 0;static 静态变量在编译的时候,初始化为 0;
若是多个变量同名,调用最近的那个变量(就近原则);
2. 栈是由一组变量组成,用数组表示,栈使用变量方式遵循后进先出。
操作栈需要一个 int num 变量,一个 int stack[10] 数组,和以下四个函数:
int num;
int stack[10];
void push(int value); // 放入变量
{
stack[num] = value;
num++;
}
int pop(); // 取出变量
{
num--;
stack[num];
}
int empty(); // 查看栈是否为空
{
return 0 == num;
}
int full(); // 查看栈是否满了
{
return 10 == num;
}
3. 秒表练习
#include <stdio.h>
#include <time.h>
#include <unistd.h> // sleep(1)语句调用
int main()
{
int start = time(0); // 获取当前时间
while(1)//死循环
{
printf("%d\r", time(0) - start); // \r指删除之前显示的,重新显示
fflush(stdout); // 强制显示
sleep(1); // 让程序休息一秒再运行,不精确,可能差几毫秒;
}
return 0;
}
4. 程序在内存中运行是分段存储的。
代码段用来存储所有语句,在运行时,代码段是不可以更改的。
栈:数据段/局部变量段,(全局变量除外)
堆:用来处理手动创建和销毁的变量
5. 变量关键字:
auto 所有局部变量默认都为 auto,所以不需要特别声明;
static 用来声明静态变量。
静态全局变量,作用域变小;不能在不同的文件中使用;
静态局部变量,作用域不变,上次运行的结果被保存下来,生命周期类似于全局变量,
但是作用域没有全局变量大(生命周期和作用域不一致,生命周期长了,作用域不变),即变量名在其他函数中不能用。
静态函数与普通函数作用域不同;仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),
内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,
应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件;
静态函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝;
register 寄存器变量,位于 cpu 里面,数量少,非常重要,一般不使用。
volatile 声明易变变量。
const 声明不可变变量,也可以定义指针。
const int *p = &value; // 也可以写为:int const *p = &value
*p = 3; // 编译错误,内容不可以修改
p = NULL; // 地址可以修改
value = 3; // const定义的是p,对value没影响
另外一种定义:
int * const p1 = &value;
*p1 = 3; // 内容可以修改
p1 = 3; // 编译错误,地址不能修改
还可以两边都加 const,
const int * const p = &value;
这样 *p 和 p 都不可以被修改;
6. 变量的指针就是指变量的地址,咱平时在程序里用的是指针变量:
指针变量:
int *p = & value;
*p = value; 或者 *p = 5;
注意第一句里的“&”;第一句为初始化,第二句为赋值;
给指针变量初始化,必须用地址,例如上面第二句赋值语句写成 p = 5; 是错误的;
同时被赋值的指针变量前也不能再加“&”,例如上面第二行赋值语句写成 *p = & value; 是错误的;
通过指针,把 5,7 赋值给数组 value[2];
int value[2];
int *p_value = value; // 指针地址必须初始化,若无法初始化,就初始化为:*p_value = NULL;
*p_value = 5; // value[0] = 5
p_value++;
*p_value = 7; // value[1] = 7
*(p_value - 1) += *p_value; // value[0] += value[1]
可以用指针变量作为返回值:
int *func()
{
static int value = 0; // 此处要用static把value静态化,否则函数结束,value生命周期结束,return返回的是野指针
return &value;
}
int main()
{
int *p = NULL;
*p = 7;
p = fun();
}
7. NULL 表示空地址,其实是数字 0 ,记录空地址的指针叫做空指针。
未初始化的指针为无效指针,所有无效指针必须初始化为空指针,即 *p = NULL;
记录无效地址的指针叫做野指针,程序中不应该出现野指针;
野指针也叫悬空指针。
8. 通过指针 *p,用 for 循环表示数组 value[4] 的遍历:for(p = value; p < value + 4; p++)
9. 把 int *p 转换为无符号字符指针:*(unsigned char *)p;
指针可以强制类型转换,转换后地址和原地址相同,但他们的类型不同,所以使用方法也不一样。
10. 指针作形参,实参必须是地址,既当输入参数,又当输出参数。
数组作形参,其实就是指针作形参。
11. 当指针变量要代表多个类型的参数时,可以如下声明:
void *p = NULL;
int i = 1;
p = &i;
但在输出或其他使用的时候,必须强制类型转换,如:
printf("%d", *(int *)p);
12. 看书笔记:
两个指针可以相减,一般用于数组;
但是两个指针不可以相加,会得到不确定结果,甚至出错;
变量的作用域指的是“变量名“的作用域,而非变量;生命周期和作用域一致;
变量和变量名是不一样的;
全局变量在程序开始前就默认初始化为 0;static 静态变量在编译的时候,初始化为 0;
若是多个变量同名,调用最近的那个变量(就近原则);
2. 栈是由一组变量组成,用数组表示,栈使用变量方式遵循后进先出。
操作栈需要一个 int num 变量,一个 int stack[10] 数组,和以下四个函数:
int num;
int stack[10];
void push(int value); // 放入变量
{
stack[num] = value;
num++;
}
int pop(); // 取出变量
{
num--;
stack[num];
}
int empty(); // 查看栈是否为空
{
return 0 == num;
}
int full(); // 查看栈是否满了
{
return 10 == num;
}
3. 秒表练习
#include <stdio.h>
#include <time.h>
#include <unistd.h> // sleep(1)语句调用
int main()
{
int start = time(0); // 获取当前时间
while(1)//死循环
{
printf("%d\r", time(0) - start); // \r指删除之前显示的,重新显示
fflush(stdout); // 强制显示
sleep(1); // 让程序休息一秒再运行,不精确,可能差几毫秒;
}
return 0;
}
4. 程序在内存中运行是分段存储的。
代码段用来存储所有语句,在运行时,代码段是不可以更改的。
栈:数据段/局部变量段,(全局变量除外)
堆:用来处理手动创建和销毁的变量
5. 变量关键字:
auto 所有局部变量默认都为 auto,所以不需要特别声明;
static 用来声明静态变量。
静态全局变量,作用域变小;不能在不同的文件中使用;
静态局部变量,作用域不变,上次运行的结果被保存下来,生命周期类似于全局变量,
但是作用域没有全局变量大(生命周期和作用域不一致,生命周期长了,作用域不变),即变量名在其他函数中不能用。
静态函数与普通函数作用域不同;仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),
内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,
应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件;
静态函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝;
register 寄存器变量,位于 cpu 里面,数量少,非常重要,一般不使用。
volatile 声明易变变量。
const 声明不可变变量,也可以定义指针。
const int *p = &value; // 也可以写为:int const *p = &value
*p = 3; // 编译错误,内容不可以修改
p = NULL; // 地址可以修改
value = 3; // const定义的是p,对value没影响
另外一种定义:
int * const p1 = &value;
*p1 = 3; // 内容可以修改
p1 = 3; // 编译错误,地址不能修改
还可以两边都加 const,
const int * const p = &value;
这样 *p 和 p 都不可以被修改;
6. 变量的指针就是指变量的地址,咱平时在程序里用的是指针变量:
指针变量:
int *p = & value;
*p = value; 或者 *p = 5;
注意第一句里的“&”;第一句为初始化,第二句为赋值;
给指针变量初始化,必须用地址,例如上面第二句赋值语句写成 p = 5; 是错误的;
同时被赋值的指针变量前也不能再加“&”,例如上面第二行赋值语句写成 *p = & value; 是错误的;
通过指针,把 5,7 赋值给数组 value[2];
int value[2];
int *p_value = value; // 指针地址必须初始化,若无法初始化,就初始化为:*p_value = NULL;
*p_value = 5; // value[0] = 5
p_value++;
*p_value = 7; // value[1] = 7
*(p_value - 1) += *p_value; // value[0] += value[1]
可以用指针变量作为返回值:
int *func()
{
static int value = 0; // 此处要用static把value静态化,否则函数结束,value生命周期结束,return返回的是野指针
return &value;
}
int main()
{
int *p = NULL;
*p = 7;
p = fun();
}
7. NULL 表示空地址,其实是数字 0 ,记录空地址的指针叫做空指针。
未初始化的指针为无效指针,所有无效指针必须初始化为空指针,即 *p = NULL;
记录无效地址的指针叫做野指针,程序中不应该出现野指针;
野指针也叫悬空指针。
8. 通过指针 *p,用 for 循环表示数组 value[4] 的遍历:for(p = value; p < value + 4; p++)
9. 把 int *p 转换为无符号字符指针:*(unsigned char *)p;
指针可以强制类型转换,转换后地址和原地址相同,但他们的类型不同,所以使用方法也不一样。
10. 指针作形参,实参必须是地址,既当输入参数,又当输出参数。
数组作形参,其实就是指针作形参。
11. 当指针变量要代表多个类型的参数时,可以如下声明:
void *p = NULL;
int i = 1;
p = &i;
但在输出或其他使用的时候,必须强制类型转换,如:
printf("%d", *(int *)p);
12. 看书笔记:
两个指针可以相减,一般用于数组;
但是两个指针不可以相加,会得到不确定结果,甚至出错;