一、循环
do···while循环
先执行再判断
do
{
循环体;
}
while(条件);
先执行循环体语句,再判断条件是否成立。
do···while语句不管条件是否满足,循环体内语句都会执行一次。
二、一维字符数组
字符串函数族的函数
内存置位
i)bzero
置0
void bzero(void *s, size_t n);
参数: void *s,内存起始地址,size_t n,置多大空间
功能: 内存置0,n字节
#include <stdio.h> #include <string.h> int main(int argc, const char *argv[]) { char str[10]="hellortyu"; int i; for(i=0;i<10;i++) { printf("%d\n",str[i]); } //使用bzero函数实现内存置0 bzero(str,3); printf("******************\n"); for(i=0;i<10;i++) { printf("%d\n",str[i]); } return 0; } //输出结果 104 101 108 108 111 114 116 121 117 0 ****************** 0 0 0 108 111 114 116 121 117 0
ii)memset
原型:void *memset(void *s, int c, size_t n);
参数:void *s,置位的起始地址,
int c,要把字节置为什么内容,
size_t n置多大空间(以字节为单位)
#include <stdio.h> #include <string.h> int main(int argc, const char *argv[]) { char arr[4]="hi"; int i; for(i=0;i<4;i++) { printf("%#x\n",arr[i]); } memset(arr,16,3); printf("*********************\n"); for(i=0;i<4;i++) { printf("%#x\n",arr[i]); } return 0; } //输出结果 0x68 0x69 0 0 ********************* 0x10 0x10 0x10 0 //memset也可以对非字符类型的数据进行置位操作 #include <stdio.h> #include <string.h> int main(int argc, const char *argv[]) { int arr[4]={12,34,56,9}; int i; for(i=0;i<4;i++) { printf("%#x\n",arr[i]); } printf("******************\n"); //memset用于,非字符数据的置0 memset(arr,0,16); for(i=0;i<4;i++) { printf("%#x\n",arr[i]); } //int arr[4]={0}; //arr[0]= 0000 0000 0000 0000 0000 0000 0000 0000 //memset(arr,1,4); //从arr的起始地址开始,向后四个字节的内容全置为1 //arr[0]= 0000 0001 0000 0001 0000 0001 0000 0001 return 0; }
数组越界
- 随机值
- 段错误
三、指针
C语言可以操作内存
scanf("%d",&a); //用到了a的地址
printf("%d\n",str); //用到了str的地址
通过变量名访问变量是直接访问。
指针实际上是内存地址/内存编号,平时我们说的指针指的是保存内存地址的变量。
【1】定义
存储类型 数据类型 *变量名;
指针保存的是变量的首地址
*的含义
- *在定义指针变量时,标识定义了一个指针变量。
- *p,表示的是访问地址中的数据,解引用。(*前面是否有数据类型)
&的含义
- 取变量的地址
- &按位与,位运算
【2】指针的初始化和赋值
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 100;
int *p; //只定义不初始化,p是一个野指针,没有明确指向的指针
printf("%d\n",*p); //野指针的间接访问,可能是段错误也可能是随机值
int b = 90;
p = &b; //给指针变量赋值, 让指针变量p指向了变量b
*p = 12;
printf("%d\n",b);
int *p1 = &a; //定义了一个指针变量p1并让他指向变量a
int *p2 = NULL; //空指针
int *p3 = p1; //定义了一个指针p3,并用指针变量p1的值给他初始化
//printf("%d\n",*p2); //空指针的间接访问一定会段错误
printf("%d\n",*p1); //100
printf("**************\n");
//通过指针变量p1,操作a
*p1 = 10;
printf("%d\n",a);
return 0;
}
野指针对程序而言是有害的,尽量不要定义野指针,如果不知道指向,指向NULL
练习:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 100,b = 90,temp1;
int *p1=&a,*p2=&b,*temp; //p1指向a,p2指向b
printf("交换前%d\t%d\n",a,b);
/*
temp = p1;
p1 = p2;
p2 = temp; //改变两个指针的指向*/
temp1 = *p1;
*p1 = *p2;
*p2 = temp1;
printf("交换后%d\t%d\n",*p1,*p2);
return 0;
}
【3】指针变量的大小
指针变量的大小,只和操作系统有关和数据类型无关。
指针的数据类型决定了指针+1,-1向后或者向前偏移的字节大小
64位8Byte,32位4Byte
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 100;
int *p = &a; //p指向a
char c = 'a';
char *p1 = &c; //让指针p1指向字符变量c
printf("sizeof(p)=%ld\nsizeof(p1)=%ld\n",sizeof(p),sizeof(p1));
return 0;
}
【4】指针的运算
算术运算和关系运算是有意义的
关系运算,它通常用来判断是否指向同一片空间
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 100;
int *p = &a; //p指向a
char c = 'a';
char *p1 = &c; //让指针p1指向字符变量c
printf("p=%p\n",p);
printf("int *p-1=%p\n",p-1); //p向后偏移4个字节
printf("%p\n",p1);
printf("char *p1+1=%p\n",p1+1); //p1向后偏移了1个字节
return 0;
}
关系运算
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 100;
int *p1 = &a,*p2=p1; //定义了整形指针p1和整形指针p2
if(p1!=p2)
{
printf("p1和p2指向的不是同一片空间\n");
}
else
printf("p1和p2指向同一片空间\n");
return 0;
}
【5】大小端存储
小端存储:数据地位放地址低位,日常使用的计算机都是小端存储
大端存储:数据低位放地址高位,TCP/IP通信
#include <stdio.h>
int main(int argc, const char *argv[])
{
int a = 0x12345678;
char *p = &a;
printf("%#x\n",*p); //0x78小端存储
//判断大小端
if(*p==0x78)
{
printf("小端存储\n");
}
else
{
printf("大端存储\n");
}
return 0;
}
【6】指针和一维数组
#include <stdio.h>
int main(int argc, const char *argv[])
{
int arr[5]={12,90,87,6,5};
int *p = arr; //让指针p指向arr数组
//有如下的等价关系
//p+i<==>arr+i
//*(p+i)<==>*(arr+i)
//p[i]<==>arr[i]
printf("arr=%p\n",arr);
printf("p=%p\n",p);
printf("&arr[0]=%p\n",&arr[0]);
printf("arr+1=%p\n",arr+1);
printf("p+1=%p\n",p+1);
printf("&arr[1]=%p\n",&arr[1]);
printf("&p[1]=%p\n",&p[1]);
//arr[1] <==> *(p+1);
//[3]<==>先偏移三个偏移量,再取*
//printf("arr++=%p\n",arr++); arr是一个地址常量
printf("p++=%p\n",p++);
return 0;
}
if(&arr[2]>&arr[1])
{
printf("arr[2]再更高字节的位置\n");
}
练习:
1、通过指针指向一维数组,实现数组中元素的输入和输出。
#include <stdio.h> int main(int argc, const char *argv[]) { int arr[5]={12,90,87,6,5}; int *p = arr; //让指针p指向arr数组 int i; for(i=0;i<5;i++) { scanf("%d",p+i); } for(i=0;i<5;i++) { printf("%d\n",*(p+i)); } return 0; }
作业:
1.整理思维导图
2.使用指针实现冒泡排序
3.课上代码再整理一遍
4.尝试实现使用指针实现一维字符数组的输入输出