变量、数组、指针、函数等概念

#include <stdio.h>

int main(int argc, char *argv[])
{
/*
 * 函数指针:专门用来存放函数地址的指针
 * 函数地址:函数的入口地址,用函数名来代表
 * 当一个函数指针指向了一个函数,便用该指针来调用该函数,将函数作为参数来传递给函数指针
 * 函数指针        (低优先级-》高优先级),即从低优先级开始读
 * 函数指针名称
 * 函数指针变量:
    <数据类型> (*<函数指针名称>)(<参数列表说明>);
【其()不能缺少,是表明指向函数的指针】
【也是区分函数指针和指针函数的关键 】
 * 函数指针类型
        typedef  函数指针变量

举例:

函数声明: int  (*PF)(int,int);        或者        int (*PF)(int a,int b);

*PF:函数指针,可以用该指针调用一个函数

函数定义: ①PF = plus        指向一个函数,为下一步调用做准备

                   printf("%d\n",(*PF)(x,y));

                   int plus(int a,int b){ 返回计算过的值};

                  ②printf("%d\n",test(15,5,plus));        将函数作为参数来传递给函数指针

                   int test(int a,int b,int (*PF)(int,int)){返回函数指针变量的值}


===========================================================
 *指针函数:
    <数据类型> *<函数名称>(<参数说明>){语句序列;}
    *函数名称:说明该函数返回一个地址量

举例:

char  *mystrcpy(char *dest,const char *src){

        char *p = dest;

        while(*dest++ = *src++);

        return p;

}

char *mystrcat(char *dest,const char *src){

        char *p = dest;

        while(*dest++);

        dest--;

        while(*dest++ = *src++);

        return p;

}


 *
 *变量: <存储类型>  <数据类型>  <变量名>
 *指针: <存储类型>  <数据类型> *<指针变量名>

*一维数组:<存储类型><数据类型><数组名>[元素的个数];

*二维数组:<存储类型><数据类型><数组名>[行] [列];

数组指针:<存储类型>  <数据类型>  (*指针变量名)[数组元素个数]

*指针数组(行指针): <存储类型>  <数据类型>  *<指针变量名>[参数类型及个数]

也可以这样辨认:后结合性 先结合性      int *p[N];整形的指针数组,因为先结合数组,再结合指针
 */

/*===========================================*/

//数组指针:
// 数据类型:指向的数组里面元素的数据类型
// 指针的数据类型:指向数据的数据类型(数据==》数组)
// 数组的数据类型:数组里面元素的数据类型
    int (*p)[10] = &a;//sz_pointer
//一个指向包含10个int元素的数组指针,注意:是一个指针
//这10个int元素被赋上a数组的地址,从入口地址开始
    

    printf("变量、指针、指针函数、函数指针的格式及概念.\n");
    return 0;

/*===========================================*/

//指针数组(行指针):

// int *p[10]        是一个数组,该数组存储存储着十个指针,

//比如:int *p[2] = {"hello","world"};       

注意:该指针数组存储的是hello和world两个字符串的首地址,是首地址、是首地址、不是字符串!!!

//**数组是地址常量,指针是地址变量,数组名可以在运算中作为指针参与,但不允许被赋值.**//

0维    ===》    1维    ===》    2维
元素      元素的地址、一级指针   二级指针、一级指针的地址
元素    一维数组、一维数组名   二维数组名、行地址(行指针)
    
升维 -- &
降维 -- * []                 [] 偏移并引用   *引用

int arr[3][4] = {0};
int (*p)[4] = arr;//int (*p)[4];
				  //p = arr;

arr[i][j] = p[i][j] = *(p[i] + j) = (*(p + i))[j] = *((*(p + i)) + j)
    
    arr[0][0] -- 元素
    p[0][0] --元素
    *p + 1 -- &arr[0][1]                // *p 代表p这个行指针数组的首地址,即&p[0][0]
    arr[2] -- &arr[2][0]
    *p[1] -- 元素arr[1][0]             //    *(p+1)
    (*p + 1))[1] -- 元素a[0][2]        //由于有[1],指偏移并引用,引用要降维,所以为元素
                                       //   *((*p+1)+1)
    (p+1)[3] -- &a[4][0]               // 虽然会越界,即无法访问,但是逻辑上是如此的
    p+3 -- &arr[3]

arr[0]   

*p☞该单元格

*p+1*p+2
arr[1]
arr[2]

例子1:

/*===============================================
*   文件名称:t3.c
*   创 建 者:     
*   创建日期:2022年03月25日
*   描    述: 列指针遍历二维数组

================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{
    int a[][3] = {3,2,1,5,4,6};
    int i,j,r,c,n,*p;
    p = &a[0][0];
    r = sizeof(a)/sizeof(a[0]);
    c = sizeof(a[0])/sizeof(int);
    n = sizeof(a)/sizeof(int);

    for(i=0;i<r;i++)
        for(j=0;j<c;j++)
            printf("%d %p\n",a[i][j],&a[i][j]);
    printf("\n");
    for(i=0;i<n;i++)
        printf("%d %p\n",*(p+i),p+i);

    return 0;
} 

例子2:

/*===============================================
*   文件名称:t3_hang.c
*   创 建 者:     
*   创建日期:2022年03月25日
*   描    述:行指针遍历数组
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int a[][3]={1,2,3,4,5,6};
    int i,j,r,c,(*p)[3];

    p=a;
    r = sizeof(a)/sizeof(a[0]);
    c = sizeof(a[0])/sizeof(int);

    for(i=0;i<r;i++){
        for(j=0;j<c;j++){
     printf(" a[i][j]=%d\n *((a+i)+j)=%d\n *(a[i]+j)%d\n",a[i][j],*(*(a+i)+j),*(a[i]+j));
     printf(" a[i][j]=%d\n *(*(p+i)+j)=%d\n *(p[i]+j)=%d\n", a[i][j],*(*(p+i)+j),*(p[i]+j));
        }
    }

    return 0;
}

例子3:

/*===============================================
*   文件名称:t4.1.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:理解指针数组名
*   功    能:用指针数组遍历二维数组所有元素
================================================*/
#include <stdio.h>

//指针数组的数组名,也代表着数组的起始位置。
/*
 * 由于数组的元素已经是指针了,
则数组名就是数组首元素的地址,
因此数组名就是指针的地址,即多级指针。
*/
/*  int* p[N];
    p:&p[0];
    p[0]:int*;
    &p[0]:int**;    */
//  用指针存储数组的起始位置为p或&p[0]
//  则          int **q=p;
//  p=>&p[0]=>int **q
//  p[0]=>int *q
int main(int argc, char *argv[])
{ 
    int a[3][2]={1,2,3,4,5,6};
    int* p[3],i,j;
    int **q;

    p[0]=a[0];
    p[1]=a[1];
    p[2]=a[2];
    q=p;

    for(i=0;i<3;i++){
        for(j=0;j<2;j++){
printf("%d %d %d\n",*(p[i]+j),*(*(p+i)+j),p[i][j]);
printf("%d %d %d\n",*(q[i]+j),*(*(q+i)+j),q[i][j]);
printf("===========\n");
        }
    }

    return 0;
}

例子4:

/*===============================================
*   文件名称:t4.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:指针数组的定义及初始化
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int m=100,n=200;
    int *p,*q;
    p=&m;
    q[0]=&m;
    q[1]=&n;
    printf("sizeof(p)=%ld\n",sizeof(p));
    printf("&m=%p &n=%p\n",p,(p+1));
    printf("&m=%p &n=%p\n",&m,&n);
    printf("p[0]=%p p[1]=%p\n",p[0],p[1]);
    printf("q=%p &q[0]=%p &q[1]=%p\n",q,&q[0],&q[1]);
    return 0;
} 

例子5:

/*===============================================
*   文件名称:t5.2.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:字符指针数组
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{ 
    char s1[]="welcome";
    char s2[]="to";
    char s3[]="Liunx";

    char* a1[3]={s1,s2,s3};
    char* a2[3]={"welcome","to","Liunx"};
    char** p;
    p=a1;
    printf("array1:%s %s %s\n",a1[0],a1[1],a1[2]);

    for(int i=0;i<sizeof(a2)/sizeof(char*);i++)
        printf("%s",*(p+i));
    printf("\n");

    p=a2;
    printf("array2:%s %s %s\n",a2[0],a2[1],a2[2]);
    for(int i=0;i<sizeof(a2)/sizeof(char*);i++)
        puts(*(p+i));
    puts("\n");

    return 0;
}

例子6:

/*===============================================
*   文件名称:t5.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:字符指针,用字符数组存串
*   功    能:实现字符串的倒序
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{ 
    char s[10];
    char *p,*q,tmp;

    printf("please input a string\n");
    gets(s);
    p=s;
    q=s + strlen(s) - 1;
//  q=s+s.length
//由于字符串是一样的,因此只需要比较其部分字符的长度
    puts(q);
    while(p<q){
       tmp = *p;
        *p = *q;
        *q =tmp;
        p++;
        q--;
    }
    printf("%s\n",s);

    return 0;
} 

例子7:

/*===============================================
*   文件名称:t6_1.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:指针函数的定义和使用
*   指针函数:返回值是指针
================================================*/
#include <stdio.h>
#include <string.h>
char* mystring(void){
    static char str[20]={0};
//  静态变量,当程序结束后才回收内存
//  char str[20]={0};
//  没有 static 就相当于一个局部数组,放在堆栈中,函数执行完自动释放.
    strcpy(str,"welcome");
    return str;
}
char* mystring1(void){
    char *str1="welcc";
//  字符串常量与静态变量类似
    return str1;
}
int main(int argc, char *argv[])
//  main(参数个数,指针->具体的参数)
{ 
    puts(mystring());
    puts(mystring1());

//    char *str2="aa";
//    复制的字符串需要是一个变量,而不是字符串常量
    char str2[10]="hsdhakba";
    strcpy(str2,"welcome");
    puts("\n");
    puts(str2);
    return 0;
}

例子8:

/*===============================================
*   文件名称:t6_2.c
*   创 建 者:     
*   创建日期:2022年03月28日
*   描    述:指针函数mystring()返回一个堆空间上的地址str.
================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *mystring(void){
    char *str = NULL;
    str = (char*)malloc(20);
    if(str==NULL){
        puts("malloc error\n");
        return str;
    }
    strcpy(str,"hello");
    return str;
}
int main(int argc, char *argv[])
{ 
    char* s;
    if((s=mystring())!=NULL){
        printf("%s\n",s);
        free(s);
    }
    return 0;
} 

例子9:

/*===============================================
*   文件名称:t6_function.pointer.c
*   创 建 者:     
*   创建日期:2022年03月29日
*   描    述:声明一个函数指针变量,如何为函数指针赋值及如何通过函数指针来调用函数.
================================================*/
#include <stdio.h>
int test(int a,int b,int (*FP)(int,int));
int plus(int a,int b);
int minus(int a,int b);
int plus(int a,int b){
    return (a+b);
}
int minus(int a,int b){
    return (a-b);
}
int test(int a,int b,int (*FP)(int,int)){
    return (*FP)(a,b);
}
int main(int argc, char *argv[])
{ 
    int x=5,y=8;
    int (*FP)(int,int);
    FP=plus;
    printf("%d\n",(*FP)(x,y));
    FP=minus;
    printf("%d\n",(*FP)(x,y));
    printf("%d\n",test(15,5,plus));
    printf("%d\n",test(15,5,minus));
    return 0;
} 

函数:

/*===============================================
*   文件名称:t6_function.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:函数、接口、封装、复用、模块化
================================================*/
#include <stdio.h>

void funs(){
    printf("Please hammer Zhuoyang Shi fart!\n");
}
void fun(char* behavior,char* name){
behavior="Please hammer fart again!";
name="Zhuoyang Shi:";
printf("%s %s\n",name,behavior);
}
int main(int argc, char **argv)
{
    char* be;
    char* na;
    funs();
    fun(be, na);

    return 0;
}
/*===============================================
*   文件名称:void_.c
*   创 建 者:     
*   创建日期:2022年03月27日
*   描    述:
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{
    int m=100;
    void* p;

    p=(void*)&m;
//  invalid use of void expression
//  无效使用void表达式.
//  这里可以不改,其对应着输出语句,printf()要改

 printf("m:%d\n&m:%p\np:%p\n*p:%d\n",m,&m,p,*(int*)p);

//  printf("m:%d\n&m:%p\np:%p\n*p:%d\n",m,&m,p,*p);
//  dereferencing ‘void *’ pointer.
//  无效使用void表达式对“void *”指针进行引用.
    return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值