C语言的格式输出,%c,%y这些代表你要输出的数据的数据类型;%d 表示输出十进
制有符号的整数。
1、%u 十进制无符号整数。
2、%f 表示输出浮点数。
3、%s表示输出 字符串。
4、%c表示输出单个字符。
5、%p表示输出指针的值。
6、%e表示输出指数形式的浮点数。
前言
- 指针是一个变量,用来存放地址,地址唯一标识一块内存空间。
- 指针的大小是固定的4/8个字节。
- 指针有类型,指针的类型决定了指针的±整数的步长,指针解引用的操作时候的权限。
1.字符指针
char ch='w';
char *cp=&ch; //用来存放地址
int main(){
const char *str="abcde"; //这里是把字符串abcde的首地址放在了指针变量里面
//abcde是常量字符串
// const 使变量里面的内容不可改
//*str='m'; // 不可以这样写,常量字符串不可以被修改
printf("%c\n",*str);
//a
printf("%s\n",*str);
//abcde
}
2.数组指针
数组指针是指针,
int *p=NULL; //p是整形指针,指向整形的指针
char *p=NULL; //p是字符指针,指向字符的指针
int arr[10]={0};
//arr 首元素的地址;
//&arr[0] 首元素的地址
//&arr 数组的地址
int arr[5]={1,2,3,4,5};
int (*p)[5]=&arr; //存储数组的地址
char * arr[5];
char * (*pa)[5]=&arr; //第二个*表示pa是一个指针,pa变量的名字,5 pa指向的数组是5个元素,第一个*表示 pa指向的数组是char*类型的数组。
int arr[]={1,2,3,4,5,6,7,8,9,10};
int (*p)[10]=&arr;
int i=0;
for(i=0;i<10;i++){
printf("%d ",*(*p+i)); //*p==arr 首元素地址
}
//for(i=0;i<10;i++){
//printf("%d ",(*p)[i]);
//}
//参数是指针的形式
void print(int (*p)[4],int x,int y){
int i=0;
for(i=0;i<x;i++){
int j=0;
for(j=0;j<y;j++){
printf("%d ",*(*(p+i)+j)); //*(p+i)这一行的数组名
}
printf("\n");
}
}
int main(){
int arr[3][4]={{1,2,3,4},{2,3,4,5},{3,4,5,6}};
print(arr,3,4);// arr首元素(第一行)地址,二维数组的首元素地址就是第一行地址
int arr1[]={1,2,3,4,5,6,7};
int *p=arr1;
for(i=0;i<7;i++){
printf("%d ",arr1[i]);
printf("%d ",*(p+i));
printf("%d ",*(arr1+i));
printf("%d ",p[i]);
}
}
3.指针数组
指针数组使数组,用来存放指针
int arr[4]={0}; //整形数组
char arr[5]={0}; // 字符数组
int *p[10]; //用来存放整形指针的数组
小试一手
int main(){
int arr1[]={1,2,3,4,5};
int arr2[]={2,3,4,5,6};
int arr3[]={3,4,5,6,7};
int *parr[3]={arr1,arr2,arr3};分别把三个首元素的地址存进去
//打印三个数组
for(i=0;i<3;i++){
for(j=0;j<5;j++){
printf("%d ",*(parr[i]+j));
}
}
}
int arr[10];
int *arr[10];
int (*p)[10];
int (*arr[10])[5];
4.指针传参
一级指针传参
void print(int* p, int sz) {
int i = 0;
for (i = 0; i < sz; i++) {
printf("%d ", *(p + i));
}
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
print(p, sz);
return 0;
}
二级指针传参
void test(int** pp) {
printf("n=%d\n", * *pp);
}
int main() {
int n = 10;
int* p = &n;
int** pp = &p;
test(pp);
test(&p);
}
5.函数指针
指向函数的指针 存放函数地址的指针
int Add(int x, int y) {
int z = 0;
z = x + y;
return z;
}
int main() {
printf("%p\n", &Add); //&Add是上面函数Add的地址
printf("%p\n", Add); //Add也是上面函数Add的地址
int (*p)(int, int) = &Add; //指向函数的指针,这里可以参照数组指针
第一个int是函数返回值类型,另外两个int是参数类型
printf("%d\n", (*p)(3, 2)); //找到这个函数,然后调用这个函数,最后结果为5;
}
(* ( void (*) () ) 0) ()
void (*) () 是一个函数指针类型,
这里是把0强制转换为void (*) () 函数指针类型,0就是一个
函数地址。
这里就调用0地址处的该函数
void (*signal(int ,void(*)(int) ) ) (int)
signal(int , void(*)(int)) //这是个函数,参数是int
和函数指针。
剩余的返回值类型是void (* ) (int) 是一个函数指针,
返回值是void,指向的函数的参数是int。
6.函数指针数组
一个数组,可以存放函数的地址——函数指针数组
int Add(int x, int y) {
return x + y;
}
int Sub(int x, int y) {
return x - y;
}
int Mul(int x, int y) {
return x * y;
}
int Div(int x, int y) {
return x / y;
}
int main() {
int (*p[4])(int, int) = { Add,Sub,Mul,Div };
int i = 0;
for (i = 0; i < 4; i++) {
printf("%d\n", p[i](2, 3));
}
}
7.指向函数指针数组的指针
是一个指针,指针指向一个数组,数组的元素都是函数指针。
int Add(int x, int y) {
return x + y;
}
int main() {
int arr[10] = { 0 };
int (*p)[10] = &arr; //数组指针
int (*pfarr[4])(int, int) = {Add}; // pfarr是一个数组---这个是函数指针数组
int(* (*ppfarr)[4])(int,int) = &pfarr;
//ppfarr是一个数组指针,指针指向的数组有四个元素
//指向的数组的每个元素的类型是一个函数指针int (* )(int,int)
}
8.qsort—库函数—排序
使用qsort库函数可以排序任意类型的数
整型,字符型,结构体类型
struct Stu {
char name[20];
int age;
};
//void qsort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2)) {
//
//}
int cmp_int(const void* e1,const void* e2) {
//比较两个数的大小
return *(int*)e1 - *(int*)e2;
}
void test1() {
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
//第一个参数:待排序数组首元素的地址
//第二个参数:到排序数组的个数
//第三个参数:待排序数组的每个元素的大小,单位是字节
//第四个参数:函数指针,比较两个元素大小的地址,,此函数是自己实现,函数指针的两个参数:待排序的两个数的
int i = 0;
for (i = 0; i < sz; i++) {
printf("%d ", arr[i]);
}
}
int cmp_f(const void* e1, const void* e2) {
return ((int)*(float*)e1 - *(float*)e2);
}
void test2() {
float f[] = { 9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0 };
int sz = sizeof(f) / sizeof(f[0]);
qsort(f, sz, sizeof(f[0]), cmp_f);
int j = 0;
for (j = 0; j < sz; j++) {
printf("%f ", f[j]);
}
}
int cmp_stubyage(const void* e1, const void* e2) {
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_stubyname(const void* e1, const void* e2) {
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
void test3() {
struct Stu s[] = { {"zhangsan",30},{"lisi",20},{"wanger",10} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stubyname);
}
int main() {
test1();
printf("\n");
test2();
printf("\n");
test3();
}
int main(){
int a=10;
int *p=&a;
char ch='w';
void *pa=&a;
pa=&ch;
// void * 是无类型的指针,,可以接受任意类型的地址。
//void * 类型的指针不能进行解引用操作,也不能进行+-整数操作。
}
比较名字是比较字符串
字符串比较不能用><=比较,用库函数Strcmp函数