printf
scanf
指针
&与*的理解
存取变量中的数据有两种引用方式
- 直接引用:按变量名称存取变量的值 (int i = 10 使用变量i,这个i即等于10)
- 间接引用:将其变量的指针即该变量的内存地址,放在另一个新的变量中,则现在这个新的变量中存储的值就是原来变量的内存地址值,现在对新变量进行操作,就相当于根据原变量内存地址,对原变量进行存取操作!(指正,int &p=10,使用指针变量p等于调用地址,如果要使用它对应的值,需要加上*,下面有介绍)
为了更好理解上述内容,你来看如下知识点
& 取地址
* 指针运算符(取值运算)
关键点:& 和 * 是互为逆运算,即两个在一起相互抵消
#include <stdio.h>
int main(void) {
int p = 1;
int h = *(&p);
printf("%d", h);
return 0;
}
运行结果 1
指针变量
指针变量就是用来存储地址的变量
任何变量都有它存储的地址,这个地址是随机分配的。如:
int i = 10;
i 这个变量的地址是系统随机分配的。而我们对其进行 “&” 运算之后就可以得到它的地址,并且 (&i) 这个表达式就是一个指向i的指针
指针声明与初始化
格式指针类型 * 指针变量名;
如
int *number;
char *name;
这里介绍两种写法
普通写法
int x;
int *p;
int p = &x;
前面讲的清楚,指针变量就是用来存储地址的变量,而&是取变量的地址,所以这段代码一下子了然
省略写法
int x;
int *p = &x;
上述两种写法都声明了一个指针p,并且这个指针是指向变量 x 的
对于变量 x, (&x) 则是一个指向x的指针 (指针存放的就是地址, 而&运算得到的地址表达式也就是指向其本身的指针)
并且通过 *(指针) 取到这个地址中的值
错误写法
// 错误1
int *p;
p = 10010; //这里P是指针变量,只可以用来存储地址,而不可以存值
// 错误2
int x = 20;
printf("%d", &(*x) ); //取地址在里面,二者交换一下
// 正确形式:
int i=1, *p, *t;
p = &i;
t = p;
int h = *t;
printf("%d",h);
输出结果 1
Swap交换两个变量
#include<stdio.h>
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
printf("x=%d, y=%d n", *x, *y);
}
main()
{
int i = 13, j = 45;
swap(&i, &j);
printf("i=%d, j=%dn", i, j);
}
字符数组与指针
字符串 == 字符数组+”结尾
// 对于字符串"Hello world"相当于如下的字符数组
char hi[] = {'h','e','l','l','o',' ','w','o','r','l','d', '\0'};
printf("%c n", hi[1]); // e
printf("%c n", "Hello world"[1]); // e
因为字符串相当于字符数组,所以”Hello world”[1]越数组hi[1]的值一样
数组名 == 起始地址
int a[5] = { 1, 3, 5 };
1638196
printf("%d", a); // 1638196 #你要是打印啊a[0]的地址值也等于1638196,所以下一行代码成立
printf("%d", *a); // 1
printf("%d", *(a+1)); // 3
运行成功,表示这个变量的类型即使不是指针,也是一个地址
常见用法
int a[5] = { 1, 3, 5 };
int *p;
p = a;
printf("%d", *(p+1)); // 3
printf("%d", *(p+2)); // 5
使用指针遍历
int arr[8] = { 1, 1, 2, 3, 5, 8, 13, 21 };
int i;
int *p;
// 普通遍历
for(i = 0; i < 8; i++)
{
printf("%d ", arr[i]);
}
// 指针遍历
for(p = &(arr[0]); p <= &(arr[7]); p++)
{
printf("%d ", *p);
}
// 数组名获取指针地址
for(p = arr; p < (arr+8); p++)
{
printf("%d ", *p);
}
为了帮助大家去理解指针遍历出———》p = &(arr[0]); p <= &(arr[7]); p++
特意写出如下代码,大家观察
指针数组与数组指针
指针数组是数组,数组指针是指针
char *arr[4] = {"hello", "world", "shannxi", "xian"}; #指针数组
//arr就是我定义的一个指针数组,它有四个元素,每个元素是一个char *类型的指针,这些指针存放着其对应字符串的首地址。
char (*pa)[4]; #数组指针
结构体
可以将多种数据类型组合起来的结构
简介
struct student1
{ #包含各种不定量数据类型
int age;
float score;
char sex[2];
};
几种声明方式
常规定义
struct time {
int hour;
int minute;
int second;
};
struct time t;
声明的同时定义
struct time {
int hour;
int minute;
int second;
char sex[2]
} t;
常规定义时定义好结构体后,在外面来定义
而这里是声明的同时就定义
我们一般不推荐这种写法,而是推荐常规写法
使用结构体作为成员
struct DATE{
int year;
int month;
int day;
};
struct person {
char name[256];
struct DATE birthday;
};
struct time t;
匿名结构体
struct {
int hour;
int minute;
int second;
char sex[2]
} t;
你要不细心看,还分不出和声明的同时定义
的区别,你看struct后面是不是少了什么
结构体的引用与初始化
如下演示 整体初始化,单个初始化过程
同时也简单展示如何打印信息
#include <stdio.h>
struct student1
{
int age;
float score;
char sex;
};
int main()
{
struct student1 st={ 80, 66.6, 'F' }; //定义的同时可以整体赋值
struct student1 st2; //单独定义,自己的小错误,老是忘记写结构体的名字
st2.age = 10;
st2.score = 88;
st2.sex = 'F';
printf("%d",st.age);
return 0;
}
结构体数组
#include<stdio.h>
#include<string.h>
struct student
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
int main()
{
int i;
struct student stu[3]={
{10101,"LiuHu",'F',18,99.7,"beijing road"},
{10102,"NaoDan",'M',17,99.8,"shanghai road"},
{10103,"MaHuangTeng",'F',48,99.9,"shenzhen road"}
};
stu[2].age = 12;
strcpy(stu[2].name,"xiaoyang"); #这个地方为何如此,下面有解释
for(i=0;i<3;i++)
{
printf("%d %s %c %d %1f %s\n",stu[i].num,stu[i].name,stu[i].sex,stu[i].age,stu[i].score,stu[i].addr);
}
return 0;
}
解释
C语言只有在定义字符数组的时候才能用“=”来初始化变量,其它情况下是不能直接用“=”来为字符数组赋值的,要为字符数组赋值可以用string.h头文件中的strcpy函数来完成。
例如:
char a[10] = "123"; /*正确,在定义的时候初始化*/
char a[10];
a = "123"; /*错误,不能用“=”直接为字符数组赋值*/
strcpy(a, "123"); /*正确,使用strcpy函数复制字符串*/
所以要对game[0][0].cpart赋值应该用strcpy(game[0][0].cpart, "123");才对。
注意要使用strcpy函数要用#include <string.h>包含string.h头文件。
结构体指针
使用分量运算符"->"来获取成员
结构体指针变量说明的一般形式为: struct 结构名 *结构指针变量名
一个结构体变量的指针就是该结构体变量所占据内存段的起始地址。
可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。
同时指针变量也可以用来指向结构体数组中的元素。
结构体指针变量说明的一般形式为:
struct 结构名 *结构指针变量名
例如,在前面的例题中定义了stu这个结构,如果要说明一个指向stu的指针变量pstu,可写为
struct stu *pstu;
当然也可以在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构体指针变量也必须要先赋值才能使用
赋值就是把结构变量首地址赋予该指针变量,不能把结构名赋予该指针变量。
如果boy是被说明为stu类型的结构变量,则:
pstu = &boy;是正确的
pstu = &stu;是错误的
因为结构名和结构变量是两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不对他们分配内存空间,只有当某变量被说明为这种类型的结构时,才对该变量存储内存空间。
所以以上 pstu = &stu;是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就更方便地访问结构变量的各个成员。
其访问的一般形式为:
(*结构指针变量).成员名
或为:
结构指针变量->成员名
例如:(*pstu).num
或者:pstu->num
struct stu{
int num;
char *name;
char sex;
float score;
}boy1 = {006,"zhangzhang",'1',69.6};
int main() {
struct stu *pstu;
pstu = &boy1;
printf("%d,%s\n", boy1.num, boy1.name);
printf("%d,%s\n", (*pstu).num, (*pstu).name);
printf("%d,%s\n", pstu->num, pstu->name);
}
动态内存分配与链表
二者区别
char t[10] = "hi";
可变 -----》 内存的动态存储区-----》
数组在定义的时候在动态内存声明了相应长度的区域,其大小取决于数组的长度,而这个长度是可以修改,也就动态存储
char *p = "hi";
不可变 -----》 内存的静态存储区-----》
“hi"是常量,不能通过"hi" = "en" 来修改,指针p指向的这一块静态内存,其中的数据不能动态更改
动态内存分配
malloc函数—内存动态分配
void * malloc (unsigned int size)
在内存的动态储存区(堆)中分配一个长度为size的连续空间。其参数是一个无符号整数,返回值是一个系统所分配的,连续内存空间的起始地址
若分配内存空间失败,则返回NULL。所以在使用之前一定要判断是否为NULL
PS:该函数仅针对指针使用,使用前需要引用malloc.h库
#include<stdio.h>
#include<malloc.h>
void main()
{
char *a;
a = (char *)malloc( 10 * sizeof(char));
if( a == NULL){
printf("内存分配失败");
exit;
}else{
*a = 'H';
*(a+1) = 'e';
*(a+2) = 'l';
*(a+3) = 'l';
*(a+4) = 'o';
*(a+5) = '\n';
*(a+6) = '\0';
}
printf(a);
}
运行结果 Hello
free函数—释放动态内存
void * free (void *p)
void main()
{
char *a,*b;
a = (char *)malloc(10 * sizeof(char));
b = a;
... #代码省略,大家一看这个函数就简单,只要动态分配都要释放,这个函数放在后面用就行
free(a);
}
链表
链表的节点结构
链表的创建
共同体、枚举、typedef
自定义数据结构
- 共同体(union)
- 枚举(enum)
- 类型定义(typedef)
union 共同体
共同体是多个类型共存,实际只能存储一个类型的变量
至于格式,只需要把结构体关键字struct 换成 union
enum 枚举
定义某一个数据类型,这种类型只有几种可能,我在定义的同时将这些可能一一例举出来,这样的类型就叫做枚举
#include <stdio.h>
#include <stdlib.h>
enum BOOL{
FALSE;
TRUE;
};
int main()
{
enum BOOL flag = TRUE;
if(...)
...
}
typedef 类型定义
通过typedef来定义自己的类型
至于为什么这样做,让对方跟容易读懂代码
所以typedef可以理解为把数据类型换个名称不改变性质的这么一个功能
typedef int money
那么这个时候money就是我们定义的类型,实际上跟int没差,但是却能让人更容易读懂你的代码
定义的时候类同
int i = 10;
money m = 200;
printf("int i=%d\nmoney m=%d",i,m);
--------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
typedef int money;
int main()
{
int i = 10;
money m = 100;
printf("int i=%d\nmoney m = %d",i,m);
}
typedef常见用法
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int hour;
int minute;
} TIME;
int main()
{
原本要
struct TIME t1;
现在可以直接
TIME t1;
}