内存区域 全局变量 线程 插值查找 位域 栈的实现
栈区可以修改默认大小配置:
栈区默认的大小是1M,在vs2013中可以修改。
堆区和栈区的地址区别:
栈是连续的,向上增长,地址越来越小。类似数组。
堆是链接的,向下增长,地址越来越大。类似链表。
栈区 高地址到低地址
堆区 低地址到高地址
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 1, b = 2;
printf("%p,%p\n", &a, &b); //a的地址大于b的地址
char *p1 = malloc(1);
char *p2 = malloc(1);
printf("%p,%p\n", &p1, &p2);//p1的地址大于p2的地址
printf("%p,%p\n", p1, p2);//p1指向的地址小于p2指向的地址
return 0;
}
代码区:只读不可写
int a = 45; //a在栈上 45在寄存器
常量字符串在代码区:
char *p = "calc"; // p在栈上, “calc”在代码区
char *p = "liuwei"; //指针只存了地址
printf("%d,%d\n",sizeof(p),sizeof("liuwei")); // 4 7
全局变量的注意事项:
1. 全局变量前一定不能加上 auto 不能放在栈上。
2. 全局变量具有声明和定义的区别。
int a;int a;
int a;
这种是可以通过编译的。因为三个都属于声明。 int a;这样没有赋值的属于声明。
不过局部内,这样就不可以了,局部变量没有声明和定义的区别。
#include <stdio.h>
int a;
int a;
int a;
int main()
{
printf("%d\n", a); //结果输出0.
return 0;
}
3. 全局变量如果只有声明,没有定义,会自动初始化0。因为是在Bss段。
4. 全局如果 int a = 1; int a = 2;会出现多重定义问题。有赋值运算符的属于定义。
5. 不同文件的全局变量:
全局变量可以跨文件使用、同一个工程,不同源文件,不能出现两个同名变量的定义 。
当两个文件同时使用一个全局变量时,需要在另一个文件内,先extern声明,再使用。
因此头文件最好只声明,不要定义,免得包含多次,就会出现多定义。当然可以用ifdef避免
函数默认是全局函数:
函数默认都是全局函数,跨文件的函数可以直接使用。
a.c
#include <stdio.h>
int main()
{
gogo();
return 0;
}
b.c
#include <stdio.h>
void gogo()
{
printf("gogo\n");
}
可以直接打印出gogo,虽然在a.c里没有函数声明,因为函数默认就是全局的
但是本文件内部调用函数之前声明,或者在前面定义
#include <stdio.h>
void gogo();//函数声明
int main()
{
gogo();
}
void gogo()
{
printf("gogo\n");
}
线程:
#include <process.h> //包含线程头文件
_beginthread();//开启一个线程
#include <stdio.h>
#include <windows.h>
#include <process.h>
void runMsg(void *p)
{
MessageBoxA(0, "hello", "world", 0);
}
void main()
{
_beginthread(runMsg, 0, NULL);
_beginthread(runMsg, 0, NULL);
_beginthread(runMsg, 0, NULL);
getchar();//不加getchar()不行,因为主线程结束了,其他线程都挂掉了
}
线程传递参数:
#include <stdio.h>
#include <windows.h>
#include <process.h>
void run(void *p)
{
MessageBoxA(0, "hello", p, 0);
}
int main()
{
_beginthread(run, 0, "ABC");
_beginthread(run, 0, "CDE");
_beginthread(run, 0, "XYZ");
getchar();
return 0;
}
如果想传递多个参数,可以传递结构体的指针
#include <stdio.h>
#include <windows.h>
#include <process.h>
struct STU
{
char name[10];
char title[10];
};
struct STU stu[3] = { {"hello","world"}, {"fuck","shit"}, {"apple","pear"} };
void run(void *p)
{
struct STU *tmp = (struct STU *)p;
MessageBoxA(0, tmp->name, tmp->title, 0);
}
int main()
{
for (int i = 0; i < 3;i++)
{
_beginthread(run, 0, &stu[i]);
}
getchar();
return 0;
}
位域实战代码:
通过位域实现输入一个数,输出其补码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef struct
{
unsigned char ch1 : 1;
unsigned char ch2 : 1;
unsigned char ch3 : 1;
unsigned char ch4 : 1;
unsigned char ch5 : 1;
unsigned char ch6 : 1;
unsigned char ch7 : 1;
unsigned char ch8 : 1;
}bit;
int main()
{
int num;
scanf("%d", &num);
bit *mybit =
#for (int i = 3; i >= 0; i--) //地址要从高字节打到低字节
{
printf("%d%d%d%d %d%d%d%d ",
mybit[i].ch8, mybit[i].ch7, mybit[i].ch6, mybit[i].ch5,
mybit[i].ch4, mybit[i].ch3, mybit[i].ch2, mybit[i].ch1);
}
return 0;
}
插值查找(二分查找升级版,注意只能在有序并且分布均匀的情况下查找)
#include <stdio.h>
int find(int *a, int n, int key)
{
int low = 0, high = n - 1;
int mid, count = 0;
while (low <= high)
{
printf("查找第%d次\n", ++count);
//mid = (low + high) / 2; 二分查找bug版本
//mid = low + (high - low) / 2; 二分查找正确版
mid = low + (high - low) * (key - a[low]) / (a[high] - a[low]);//插值查找
if (a[mid] == key)
return mid;
else if (a[mid] < key)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
int main()
{
int i;
int a[1024 * 100];
for (i = 0; i < 1024 * 100; i++)
a[i] = i;
int pos = find(a, 1024 * 100, 102);
if (pos != -1)
printf("%d %d\n", pos, a[pos]);
else
printf("没有找到\n");
}
注:二分查找的一个bug
见:排序算法
数据结构栈,实现递归:
栈的数据结构实现:
#include <stdio.h>
#include <string.h>
#define N 50
struct stack
{
int top;
int data[N];
};
void init_stack(struct stack *p)
{
p->top = -1;
memset(p->data, 0, sizeof(int)*N);
}
int is_empty(struct stack *p)
{
if (p->top == -1)
return 1;
else
return 0;
}
int is_full(struct stack *p)
{
if (p->top == N - 1)
return 1;
else
return 0;
}
void push_stack(struct stack *p, int key)
{
if (is_full(p))
return;
p->top++;
p->data[p->top] = key;
}
int pop_stack(struct stack *p)
{
if (is_empty(p))
return -1;
int data = p->data[p->top];
p->top--;
return data;
}
int main()
{
struct stack mystack;
init_stack(&mystack);
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i;
for (i = 0; i < 10; i++)
{
push_stack(&mystack, a[i]);
}
while (!is_empty(&mystack))
{
printf("%d\n", pop_stack(&mystack));
}
return 0;
}
递归打印一个整数的二进制
#include <stdio.h>
void bin(int num)
{
if (num == 0)
return;
bin(num / 2);
printf("%d\n", num % 2); // 1 0 1 0
}
int main()
{
bin(10);
return 0;
}
用上面的栈数据结构实现以上的递归。
int main()
{
struct stack mystack;
init_stack(&mystack);
int num = 10;
while (num)
{
push_stack(&mystack, num % 2);
num /= 2;
}
while (!is_empty(&mystack))
{
printf("%d\n", pop_stack(&mystack));
}
return 0;
}