精华内容
下载资源
问答
  • 2020-04-13 09:29:13

    c语言指针比较辨析

    如题。

    指针比较只对相同对象才有意义:如果两个指针指向同一个简单对象,则相等;如果指针指向同一个结构的不同成员,则指向结构中后声明的成员的指针较大;如果指针指向同一个联合的不同成 员,则相等;如果指针指向一个数组的不同成员,则它们之间的比较等价于对应下标之间的 比较。如果指针 P 指向数组的最后一个成员,尽管 P+1 已指向数组的界外,但 P+1 仍比 P 大。 其它情况下指针的比较没有定义。
    更多相关内容
  • C语言指针,便于理解

    千次阅读 2021-05-25 06:40:01
    一、指针变量定义C语言种变量:其中变量(普通变量)存储内容值;地址变量(指针变量)存储地址值。...(2)在定义指针变量时,指针变量名前的“*”表示现定义的是一个指针类型的变量。星号并不是指针变量名的...

    一、指针变量定义

    C语言有两种变量:

    其中变量(普通变量)存储内容值;地址变量(指针变量)存储地址值。

    1、定义的格式:

    类型名 *指针变量名;

    如:

    int a,b,*p1,*p2;

    float x,y,*p3,*p4;

    chars,*p5,*p6;

    注:

    (1)定义变量(普通变量、指针变量)都必须在前面有类型名。

    (2)在定义指针变量时,指针变量名前的“*”表示现定义的是一个指针类型的变量。星号并不是指针变量名的一部分,只有一个标志。

    (3)指针变景专口用来存地址,禁止将一个整型值直接t给一不着变量。

    int a,b,*p;

    a=1000;

    b=2000;

    p=4000;//错误只能存地址值

    2、指针变量的引用

    “&”取地址运算符,通过&运算符可以取出普通变量的地址。

    “”指针运算符,可以取出指针变量所指向的普通变量的值,(间接引用普通量)

    *指针变量名

    如:

    int a,b=20,c=30,d=40,*p;

    p=&d;

    a=*p;a=d;

    指针方法:

    口诀:内容变量画房子,指针变量画指向,定义也要初始化,

    口诀:地址变量得地址,得谁地址指向谁,有*为内容值,不是读就是写,=号左边是写操作

    画图:数组,static,指针,链表,文件

    注:

    (1)可以通过赋值使一个指针变量“指向”某一普通变量(指针变量=&普通变量)。

    (2)在C语言中正确的做法是先让指针变量指向一个确定的存储单元后,再通过该指针变量引用它所指向的存储单元,如:

    int *p;//p的"房子"是随机的,指针是任意指的,如果指针指向系统区,则代价极高

    *p=200;危险!//因此在C语言中指针必须定义且初始化

    (3)变量名(普通变量、指针变量)都表示其存储单元内的值。

    pl=p2;/*pl指向了p2所指向的单元*/

    读出p2的内容值写到p1的"房子"里

    (4)若指针变量p指向变量a,即将变量a的地址赋给了指针变量p。

    如:int a=20,*p=&a;则有下列结果(等价表):

    A、*p<=>a

    B、p<=>&a

    C、&*p<=>&a<=>p

    D、*&a<=>*p<=>a

    E、(*p)++ a++都是给变量a的值加1。

    (*p)-- a--

    ++(*p) ++a ++*p

    --(*p) --a --*p

    (5)所有的指针变量在内存中分配的字节数相同。sizcof()

    int *p1;

    float *p2;

    double *p3;

    指针变量永远占两个字节(地址),前面类型表示的是该指针指向的内容值的类型

    例1:

    请输出下列程序的结果

    void fun(int*x,int*y)

    {printf("%d %d",*x,*y);

    *x=3;

    *y=4;

    }

    main()

    {int x=1,y=2;

    fun(&y,&x);

    printf("d% d%",x,y);

    }

    输出结果:2 14 3

    例2:

    #include请输出下列程序的结果

    void swap(int*pl,int*p2)

    {int temp;

    temp=*p1;

    *p1=*p2;

    *p2=temp;}

    main()

    {

    int a,b;

    int *p1=&a,*p2=&b;

    scanf("%d%d",pl,p2);

    swap(pl,p2);

    printf("%d,%d",*pl,*p2);

    }

    键盘输入2 5

    输出结果:5,2

    改动后:

    #include请输出下列程序的结果

    void swap(int*pl,int*p2)

    {int *temp;

    temp=pl;

    p1=p2;

    p2=temp;

    }

    main()

    {int a,b;

    int*p1=&a,*p2=&b;

    scanf("%d%d",pl,p2);

    swap(p1,p2);

    printf("%d,%d",*p1,*p2);

    }

    键盘输入:2 5

    输出结果为: 2,5

    例3:

    #include请输出下列程序的结果

    void swap(int*pl,int*p2)

    {int *temp;

    *temp=*pl;

    *p1=*p2;

    *p2=*temp;}

    main()

    {int a,b;

    int *p1=&a,*p2=&b;

    scanf("%d%d",pl,p2);

    swap(pl,p2);

    printf(%d,%d",*p1,*p2);

    }

    键盘输入:2 5

    结果:是5,2吗?错误!会报错哦,指针变量不能任意指,必须初始化程序中temp没有初始化所以很危险哦

    二、一维数组与指针变量

    说明:(1)

    int fun(int a[10])<=>int fun(int*a)<=>int fun(int a[])

    若数组做为形参,则将数组名做指针变量来处理。

    指向数组的指针变量

    1、指向数组元素的指针变量

    由于数组元素与普通一样,所以定义指向数组元素的指针变量与定义指向普通变量的指针变量完全一样

    如:

    int s[10],a,b;

    int b[3][6];

    int*p;

    p=&a;

    p=&s[2];

    p=&b[2][4];

    2、指向一维数组的指针变量

    注:数组a[]

    (1)在C语言中规定:数组名a代表数组的首地址,而且是一个地址常量,且a<=>&a[0]

    如:

    int a[10];intp;P=a;<=>P=&a[0];

    (2)当指针变量指向数组中的某一个元素时,指针变量加1后指向数组的下一个元素,指针变量减1时指向数组中前一个元素。

    如:

    float a[10];floatp;p=&a[4];则p-3指向?---->a[1]

    (3)

    int a[N],*p=a;

    p+i a+i &a[i] 地址三者相互等价

    *(p+i) *(a+i) a[i] p[i] 元素四等价

    当指针变量指向数组时,下标运算符(一级) ([])用于数组也可用于指针变量后

    a)*(p+i)*(a+i)a[i] p[i]

    b)p++、++p、p+=1、p=p+1

    c)p--、--p、p-=1、p=p-1

    d)*p++*(p++) *p-- *(p--)

    e)*++p *(++p) *--p *(--p)

    f)(*p)++ ++(*p)++*p

    g)(*p)-- --(*p)--*p

    如:

    若有定义:

    int b[5]={10,30,20,15,40};

    int*q=b+2;

    则:

    ++二级从右向左运算

    q++表达式的值?,同时q指向了?----->(q++)--->20,b[3]

    ++q表达式的值?,同时q指向了?----->(++q)---->15,b[3]

    (q)++表达式的值?同时q指向了?21,b[2]

    ++(q)表达式的值?同时q指向了?21,b[2]

    例:

    举例指针在数组中的使用:

    main()

    {int*p,a[3],I;

    p=a;

    for(i=0:i<3;i++) //for(i=0;i<3;i++)

    scnaf("%d",p++); // scanf("%d",&a[i]);

    printf("\n\n");

    for(p=&a[0];p

    printf("%d",*p++); //printf("%d",a[i]);

    }

    (4)若两个指针变量指向同一个数组,则这两个指针变量可以进行大小比较如:

    char s[10];charpl=s+3,p2=&s[7];

    则:

    pl>p2=>0 pl1

    p1-p2=>-4 p2-p1=>4

    (5)在形参中的数组实际上是一个指针变量,并不是真正的数组,因为该“数组名”的值是可以改变的,而真正的数组名的值是不能改变的。

    (6)若形参是数组或指针变量,则在函数中可以通过该形参改变实参的值

    三、多维数组与指针变量

    如:int a[3][4];

    a+1是跳过一行。因为二维数组名是行指针,加1是跳过一行不是一个元素切记:

    ①只有列指针才是“真正”指向元素。即指向某一个元素的存储单元

    ②一维数组名表示的是列指针;二维数组名表示的是行指针。

    注:若a是一个二维数组,则有:

    (1)a+i是行指针,即指向的是一整行。若对它加1则指向下一行

    (2)*(a+i)和a[i]一样,都是一个列指针即指向的是一个元素,

    (3)*(a+i)+j和a[i]+j一样,都表示元素a[i][j]的地址。即与&a[i][j]等价

    *(a+i)+j a[i]+j &a[i][j]地址三等价

    (4)*(*(a+i)+j)、*(a[]j)、(*(a+i))[j]和a[i][j]一样,都表示(元素四等价)

    若有以下定义:

    int w[2][3];

    则对w数组元素非法引用是:E

    A、*(w[0]+2)B、*(w+1)[2]C、w[0][0]D、*(w[1]+2)E、w[l]+2

    1、指向多维数组元素的指针变量

    如:

    int a[31[4];

    int*p=&a[0][3];

    则:

    p+1指向元素a[1][0];

    p+4指向元素a[1][3]

    p-2指向元素a[0][1]

    常用于取二维数组a元素地址的方式:

    &a[i][j]、a[i]+j、*(a+i)+j

    例:

    main()

    { int a[3][3]={1,2,3,4,5,6,7,8,9},*p;

    for(p=a[0];p

    展开全文
  • 主要介绍了在C语言中比较两个字符串是否相等的方法,分别介绍了strcmp()函数和strcasecmp()函数,注意功能区分,需要的朋友可以参考下
  • C语言指针和数组是否相等?简短的答案:不相等。详细的答案:这依赖于如何定义“相等”。指针运算和数组下标是相等的,其他方面指针和数组是不同的。一简单的例子展示相等性:#include int main(){char arr[] = ...

    这是一个简单的问题,但总是被忽略。特此翻译了一篇博客,讲的很清楚。这里是博客的原地址Are pointers and arrays equivalent in C?

    C语言中指针和数组是否相等?

    简短的答案:不相等。

    详细的答案:这依赖于如何定义“相等”。指针运算和数组下标是相等的,其他方面指针和数组是不同的。

    一个简单的例子展示相等性:

    #include

    int main()

    {

    char arr[] = "don't panic\n";

    char* ptr = arr;

    printf("%c %c\n", arr[4], ptr[4]);

    printf("%c %c\n", *(arr+2), *(ptr+2));

    return 0;

    }

    输出结果:

    t t

    n n

    注意到下标在数组和指针中都能工作,相似地,指针运算在数组和指针中都能用。

    他们如何是不同的?

    在一个很重要和基本的方式中,考虑如下代码:

    char array_place[100] = "dont't panic";

    char* ptr_place = "don't panic";

    int main()

    {

    char a = array_place[7];

    char b = ptr_place[7];

    return 0;

    }

    给a赋值时发生了什么?与给b赋值有什么不同?看一下编译器的分解是有用的:

    (Visual C++ 2005,x86,Windows XP)

    char a = array_place[7];

    0041137E mov al,byte ptr [_array_place+7 (417007h)]

    00411383 mov byte ptr [a],al

    char b = ptr_place[7];

    00411386 mov eax,dword ptr [_ptr_place (417064h)]

    0041138B mov cl,byte ptr [eax+7]

    0041138E mov byte ptr [b],cl

    C语言中数组的语义指示数组名作为数组第一个元素的地址。因此,在给a赋值的过程中,数组的第8个字符被偏移为array_place[7]的值,移动结果地址的内容到寄存器al,然后再赋给a。

    另一方面,指针的语义是十分不同的。指针仅仅是一个固定值,持有另一个内部变量的地址。因此,计算字符串第8个字符的偏移,CPU首先复制指针的值给一个寄存器,然后增加寄存器。这多出一个指令。

    一个图形化的解释

    c23060156383

    右边那一列是内存地址,每个格子是内存中存储的内容。如图展示的是array_place的第一个单词。

    注意到array_place是内存地址0x417000的一个简单标签,因此访问array_place[7]就是访问内存地址0x417007。如我们所看到的,编译器仅仅用0x417007代替array_place[7],不需要地址的计算。

    而指针的工作方式是不同的:

    c23060156383

    ptr_place仅仅是一个变量,变量的值是一个地址。这个地址是一个字符串所在内存位置的第一个字符的地址,比较访问pointer_place[7]的分解列表能够很清楚理解编译为何如此生成编码。

    C语言的变量名仅仅是一个标签

    没有黑过编译器的程序员经常忽视指针,C语言的变量仅仅是内存空间的一个方便的数字字母组成的笔名。如果我们正在写代码,我们应该仅仅创建内存空间的标签,然后访问这些标签,代替硬编码内存值,后者是由编译器来做的。

    实际上地址不是绝对的硬编码,因为存在载入和重分配。但这在我们的讨论之外,这里就不展开细节了。

    标签是编译器在编译时分配的,从这里我们可以看出指针和数组的巨大不同。

    在函数参数中数组被转换成指针

    先看一段代码:

    void foo(char arr_arg[], char* ptr_arg)

    {

    char a = arr_arg[7];

    char b = ptr_arg[7];

    }

    问题:在这里访问a和b有什么不同吗?

    回答:一点也没有!

    这是编译器的展开:

    char a = arr_arg[7];

    00412DCE mov eax,dword ptr [arr_arg]

    00412DD1 mov cl,byte ptr [eax+7]

    00412DD4 mov byte ptr [a],cl

    char b = ptr_arg[7];

    00412DD7 mov eax,dword ptr [ptr_arg]

    00412DDA mov cl,byte ptr [eax+7]

    00412DDD mov byte ptr [b],cl

    这是因为数组在函数的参数中总是倍转换成指针。

    char arr_place[]的参数声明仅仅是char* arr_place的语法糖。

    这里引用K&R2:

    当数组名作为函数参数时,仅仅是初始化元素的位置。在调用函数时,参数是一个局部变量,数组名就是一个指针,一个存储内容为内存地址的变量。

    如果这看起来很奇怪,再仔细想一想。回想一下前面的图。编译器在这里别无选择,数组名作为一个标签在编译时代替要表示的地址。但一个函数在编译时并没有调用,仅在运行时调用,此时在栈中倍看做是一个参数。编译器不能处理数组内部引用作为标签和把他们替换成地址,因为它不知道实际上数组在运行时传入什么。

    展开全文
  • 深入理解C语言指针

    万次阅读 多人点赞 2019-09-28 08:36:51
    一、指针的概念 要知道指针的概念,要先了解变量在内存中如何存储的。在存储时,内存被分为一块一块的。...这段代码非常简单,就是两个变量的声明,分别赋值了 10、20。我们把内存当做一个酒店,而每个房间就...

    一、指针的概念

    要知道指针的概念,要先了解变量在内存中如何存储的。在存储时,内存被分为一块一块的。每一块都有一个特有的编号。而这个编号可以暂时理解为指针,就像酒店的门牌号一样。

    1.1、变量和地址

    先写一段简单的代码:

    void main(){
    	int x = 10, int y = 20;
    }
    

    这段代码非常简单,就是两个变量的声明,分别赋值了 10、20。我们把内存当做一个酒店,而每个房间就是一块内存。那么“int x = 10;”和“int y = 20;”的实际含义如下:

    1. 去酒店订了两个房间,门牌号暂时用 px、py 表示
    2. 让 10 住进 px,让 20 住进 py
    3. 其中门牌号就是 px、py 就是变量的地址
    4. x 和 y 在这里可以理解为具体的房间,房间 x 的门牌号(地址)是 px,房间 y 的门牌号(地址)是 py。而 10 和 20,通过 px、py 两个门牌,找到房间,住进 x、y。用户(变量的值)和房间(变量)以及房间号(指针、地址)的关系

    1.2、指针变量和指针的类型

    指针变量就是一个变量,它存储的内容是一个指针。如果用前面的例子,可以理解为指针变量就是一张房卡,房卡存储了房间号的信息。

    在我们定义一个变量的时候,要确定它的类型。int x、char ch、float、、、在定义指针变量时也是一样的,必须确定指针类型。int 变量的指针需要用 int 类型的指针存储,float 变量的指针需要用 float 类型的指针存储。就像你只能用酒店 A 的房卡存储酒店 A 中房间号的信息一样。

    二、变量的指针与指针变量

    变量的指针就是变量的存储地址,指针变量就是存储指针的变量。

    2.1、指针变量的定义及使用

    (1)指针变量的定义

    指针变量的定义形式如:数据类型 *指针名;例如:

    //分别定义了 int、float、char 类型的指针变量
    int *x;
    float *f;
    char *ch;
    

    如上面的定义,指针变量名为 x、f、ch。并不是*x、*f、*ch

    (2)指针变量的使用

    • 取地址运算符&:单目运算符&是用来取操作对象的地址。例:&i 为取变量 i 的地址。对于常量表达式、寄存器变量不能取地址(因为它们存储在存储器中,没有地址)。
    • 指针运算符*(间接寻址符):与&为逆运算,作用是通过操作对象的地址,获取存储的内容。例:x = &i,x 为 i 的地址,*x 则为通过 i 的地址,获取 i 的内容。

    代码示例:

    //声明了一个普通变量 a
    int a;
    //声明一个指针变量,指向变量 a 的地址
    int *pa;
    //通过取地址符&,获取 a 的地址,赋值给指针变量
    pa = &a;
    //通过间接寻址符,获取指针指向的内容
    printf("%d", *pa);
    

    (3)“&”和“*”的结合方向

    “&”和“*”都是右结合的。假设有变量 x = 10,则*&x 的含义是,先获取变量 x 的地址,再获取地址中的内容。因为“&”和“*”互为逆运算,所以 x = *&x。

    接下来做个小练习,输入 x、y 两个整数,然后将其中的值大的赋值给 x,小的赋值给 y。即:假设输入 x = 8,y = 9。就将 9 赋值给 x,8 赋值给 y。

    void main(){
    	//声明两个普通变量
    	int x, y;
    	//声明两个指针变量
    	int *px, *py;
    	//声明一个临时变量,用于交换
    	int t;
    	//输入两个值,赋值给 x、y
    	scanf("%d", &x);
    	scanf("%d", &y);
    	//给指针变量 px、py 赋初值(关联变量 x、y)
    	px = &x;
    	py = &y;
    	//利用指针来对比 x、y 的值,如果 x 的值比 y 的值小,就交换
    	if(*px < *py){
    		//交换步骤,其中*px == x、*py == y
    		t = *px;
    		*px = *py;
    		*py = t;
    	}
    	printf("x =  %d, y = %d", *px, *py);
    }
    
    输入:23 45
    输出结果为:x = 45, y = 23
    

    2.2、指针变量的初始化

    指针变量与其它变量一样,在定义时可以赋值,即初始化。也可以赋值“NULL”或“0”,如果赋值“0”,此时的“0”含义并不是数字“0”,而是 NULL 的字符码值。

    //利用取地址获取 x 的地址,在指针变量 px 定义时,赋值给 px
    int x;
    int *px = &x;
    //定义指针变量,分别赋值“NULL”和“0”
    int *p1= NULL, *p2 = 0;
    

    2.3、指针运算

    (1)赋值运算

    指针变量可以互相赋值,也可以赋值某个变量的地址,或者赋值一个具体的地址

    int *px, *py, *pz, x = 10;
    //赋予某个变量的地址
    px = &x;
    //相互赋值
    py = px;
    //赋值具体的地址
    pz = 4000;
    

    (2)指针与整数的加减运算

    1. 指针变量的自增自减运算。指针加 1 或减 1 运算,表示指针向前或向后移动一个单元(不同类型的指针,单元长度不同)。这个在数组中非常常用。
    2. 指针变量加上或减去一个整形数。和第一条类似,具体加几就是向前移动几个单元,减几就是向后移动几个单元。
    //定义三个变量,假设它们地址为连续的,分别为 4000、4004、4008
    int x, y, z;
    
    //定义一个指针,指向 x
    int *px = &x;
    
    //利用指针变量 px 加减整数,分别输出 x、y、z
    printf("x = %d", *px);		//因为 px 指向 x,所以*px = x
    
    //px + 1,表示,向前移动一个单元(从 4000 到 4004)
    //这里要先(px + 1),再*(px + 1)获取内容,因为单目运算符“*”优先级高于双目运算符“+”
    printf("y = %d", *(px + 1));		
    printf("z = %d", *(px + 2));
    

    (3)关系运算

    假设有指针变量 px、py。

    1. px > py 表示 px 指向的存储地址是否大于 py 指向的地址
    2. px == py 表示 px 和 py 是否指向同一个存储单元
    3. px == 0 和 px != 0 表示 px 是否为空指针
    //定义一个数组,数组中相邻元素地址间隔一个单元
    int num[2] = {1, 3};
    
    //将数组中第一个元素地址和第二个元素的地址赋值给 px、py
    int *px = &num[0], *py = &num[1];
    int *pz = &num[0];
    int *pn;
    
    //则 py > px
    if(py > px){
    	printf("py 指向的存储地址大于 px 所指向的存储地址");
    }
    
    //pz 和 px 都指向 num[0]
    if(pz == px){
    	printf("px 和 pz 指向同一个地址");
    }
    
    //pn 没有初始化
    if(pn == NULL || pn == 0){
    	printf("pn 是一个空指针");
    }
    

    三、指针与数组

    之前我们可以通过下标访问数组元素,学习了指针之后,我们可以通过指针访问数组的元素。在数组中,数组名即为该数组的首地址,结合上面指针和整数的加减,我们就可以实现指针访问数组元素。

    3.1、指向数组的指针

    如以下语句:

    int nums[10], *p;
    

    上面语句定义了一个数组 nums,在定义时分配了 10 个连续的int 内存空间。而一个数组的首地址即为数组名nums,或者第一个元素的首地址也是数组的首地址。那么有两种方式让指针变量 p 指向数组 nums:

    //数组名即为数组的首地址
    p = nums;
    //数组第一个元素的地址也是数组的首地址
    p = &nums[0];
    

    上面两句是等价的。
    如下几个操作,用指针操作数组:

    1. *p = 1,此操作为赋值操作,即将指针指向的存储空间赋值为 1。此时 p 指向数组 nums 的第一个元素,则此操作将 nums 第一个元素赋值为 0,即 nums[0] = 1。
    2. p + 1,此操作为指针加整数操作,即向前移动一个单元。此时 p + 1 指向 nums[0]的下一个元素,即 nums[1]。通过p + 整数可以移动到想要操作的元素(此整数可以为负数)。
    3. 如上面,p(p + 0)指向 nums[0]、p + 1 指向 nums[1]、、、类推可得,p+i 指向 nums[i],由此可以准确操作指定位置的元素。
    4. 在 p + 整数的操作要考虑边界的问题,如一个数组长度为 2,p+3 的意义对于数组操作来说没有意义。

    下面写一段代码,用指针访问数组的元素:

    //定义一个整形数组,并初始化
    int nums[5] = {4, 5, 3, 2, 7};
    
    //定义一个指针变量 p,将数组 nums 的首地址赋值给 p,也可以用p = &nums[0]赋值
    int *p = nums, i;			//i 作为循环变量
    
    //p 指向数组第一个元素(数组首地址),我们可以直接用间接寻址符,获取第一个元素的内容
    printf("nums[0] = %d\n", *p);			//输出结果为 nums[0] = 4
    
    //我们可以通过“p + 整数”来移动指针,要先移动地址,所以 p + 1 要扩起来
    printf("nums[1] = %d\n", *(p + 1));		//输出结果为 nums[1] = 5
    
    //由上面推导出*(p + i) = nums[i],所以我们可以通过 for 循环变量元素
    for(i = 0; i < 5; i++){
    	printf("nums[%d] = %d", i, *(p + i));
    }
    

    注:数组名不等价于指针变量,指针变量可以进行 p++和&操作,而这些操作对于数组名是非法的。数组名在编译时是确定的,在程序运行期间算一个常量。

    3.2、字符指针与字符数组

    在 C 语言中本身没有提供字符串数据类型,但是可以通过字符数组和字符指针的方式存储字符串。

    (1)字符数组方式

    这个在前面应该学习过,这里就不赘述了。

    char word[] = "zack";
    printf("%s", word);
    

    (2)字符指针方式

    指针方式操作字符串和数组操作字符串类似,可以把定义的指针看做是字符数组的数组名。在内存中存储大致如下,这里为了方便换了个字符串:在这里插入图片描述

    //除了定义一个字符数组外,还可以直接定义一个字符指针存储字符串
    char *sentence = "Do not go gentle into that good night!";
    
    //此时可以做字符串的操作
    //输出
    printf("%s", sentence);
    
    //通过下标取字符
    printf("%c", sentence[0]);
    
    //获取字符串长度,其中 strlen 是 string.h 库中的方法
    printf("%d", strlen(sentence));
    

    注:字符指针方式区别于字符数组方式,字符数组不能通过数组名自增操作,但是字符指针是指针,可以自增操作。自增自减少会实现什么效果大家可以自己尝试运行一下

    下面做个小练习,利用字符指针将字符数组 sentence 中的内容复制到字符数组 word 中:

    //定义字符数组 sentence 和 word,给 sentence 赋初值
    char sentence[] = "Do not go gentle into that good night!", word[100];
    
    //定义字符指针,指向 word
    char *ch = word;
    int i;
    
    //循环赋值
    for(i = 0; sentence[i] != '\0'; i++){
    	*(ch + i) = sentence[i];
    }
    
    //在当 i 等于 sentence 的长度(sentence 的长度不包含'\0')时,
    //i 继续自增,此时判断 sentence[0] != '\0'不符合,跳出循环,则 i 比 sentence 长度大 1
    *(ch + i) = '\0';
    
    //输出字符串,因为 ch 指向 word,所以输出结果是一样的
    printf("ch = %s, word = %s", ch, word);
    

    注:指针变量必须初始化一个有效值才能使用

    3.3、多级指针及指针数组

    (1)多级指针

    指针变量作为一个变量也有自己的存储地址,而指向指针变量的存储地址就被称为指针的指针,即二级指针。依次叠加,就形成了多级指针。我们先看看二级指针,它们关系如下:指针变量 p 指向变量 x,二级指针变量指向指针变量 p
    其中 p 为一级指针,pp 为二级指针。二级指针定义形式如下:

    数据类型 **二级指针名;
    

    和指针变量的定义类似,由于*是右结合的,所以*pp 相当于*(*p)。在本次定义中,二级指针的变量名为 pp,而不是**p。多级指针的定义就是定义时使用多个“*”号。下面用一个小程序给大家举例:

    //定义普通变量和指针变量
    int *pi, i = 10;
    //定义二级指针变量
    int **ppi;
    
    //给指针变量赋初值
    pi = &i;
    
    //给二级指针变量赋初值
    ppi = &pi;
    
    //我们可以直接用二级指针做普通指针的操作
    //获取 i 的内容
    printf("i = %d", **ppi);
    //获取 i 的地址
    printf("i 的地址为%d", *ppi);
    

    注:在初始化二级指针 ppi 时,不能直接 ppi = &&i,因为&i 获取的是一个具体的数值,而具体数字是没有指针的。

    (2)指针数组

    指针变量和普通变量一样,也能组成数组,指针数组的具体定义如下:

    数据类型 *数组名[指针数组长度];
    

    下面举一个简单的例子熟悉指针数组:

    //定义一个数组
    int nums[5] = {2, 3, 4, 5, 2}, i;
    
    //定义一个指针数组
    int *p[5];
    
    //定义一个二级指针
    int **pp;
    
    //循环给指针数组赋值
    for(i = 0; i < 5; i++){
    	p[i] = &nums[i];
    }
    
    //将指针数组的首地址赋值给 pp,数组 p 的数组名作为 p 的首地址,也作为 p 中第一个元素的地址。
    //数组存放的内容为普通变量,则数组名为变量的指针;数组存放的内容为指针,则数组名为指针的指针。
    pp = p;
    
    //利用二级指针 pp 输出数组元素
    for(i = 0; i < 5; i++){
    	//pp == &p[0] == &&nums[0],nums[0] == *p[0] == **pp
    	printf("%d", **pp);
    	
    	//指针变量+整数的操作,即移动指针至下一个单元
    	pp++;
    }
    

    3.4、指针与多维数组

    讲多维数组是个麻烦的事,因为多维数组和二维数组没有本质的区别,但是复杂度倒是高了许多。这里我主要还是用二维数组来举例,但是还是会给大家分析多维数组和指针的关系。

    (1)多维数组的地址

    先用一个简单的数组来举例:

    int nums[2][2] = {
    	{1, 2},
    	{2, 3}
    };
    

    我们可以从两个维度来分析:

    1. 先是第一个维度,将数组当成一种数据类型 x,那么二维数组就可以当成一个元素为 x 的一维数组。
    2. 如上面的例子,将数组看成数据类型 x,那么 nums 就有两个元素。nums[0]和 nums[1]。
    3. 我们取 nums[0]分析。将 nums[0]看做一个整体,作为一个名称可以用 x1 替换。则 x1[0]就是 nums[0][0],其值为 1。
      在这里插入图片描述

    我们知道数组名即为数组首地址,上面的二维数组有两个维度。首先我们把按照上面 1 来理解,那么 nums 就是一个数组,则nums 就作为这个数组的首地址。第二个维度还是取 nums[0],我们把 nums[0]作为一个名称,其中有两个元素。我们可以尝试以下语句:

    printf("%d", nums[0]);
    

    此语句的输出结果为一个指针,在实验过后,发现就是 nums[0][0]的地址。即数组第一个元素的地址。

    如果再多一个维度,我们可以把二维数组看做一种数据类型 y,而三维数组就是一个变量为 y 的一维数组。而数组的地址我们要先确定是在哪个维度,再将数组某些维度看成一个整体,作为名称,此名称就是该维度的地址(这里有些绕)。

    例:

    //假设已初始化,二维数组数据类型设为 x,一维数组数据类型设为 y
    int nums[2][2][2];
    
    //此数组首地址为该数组名称
    printf("此数组首地址为%d", nums);
    
    //此数组可以看做存储了两个 x 类型元素的一维数组,则 nums[0] = x1 的地址为
    printf("第二个维度的首地址为%d", nums[0]);
    
    //而 x1 可以看做存储了两个 y 类型元素的一维数组,则 y1 = x1[0] = nums[0][0]
    printf("第三个维度的首地址为%d", nums[0][0]);
    
    

    三维数组实际存储形式如下:
    在这里插入图片描述
    实际存储内容的为最内层维度,且为连续的。对于 a 来说,其个跨度为 4 个单元;对 a[0]来说,其跨度为 2 个单元;对 a[0][0]来说,跨度为一个单元。有上面还可以得出:

    a == a[0] == a[0][0] == &a[0][0][0];
    

    上面的等式只是数值上相等,性质不同。

    (2)多维数组的指针

    在学习指针与数组的时候,我们可以如下表示一个数组:

    int nums[5] = {2, 4, 5, 6, 7};
    int *p = nums;
    

    在前面讲指针数组时,所有指针数组元素都指向一个数字,那么我们现在可以尝试用指针数组的每个元素指向一个数组:

    //定义一个二维数组
    int nums[2][2] = {
    	{1, 2},
    	{2, 3}
    };
    
    //此时 nums[0]、和 nums[1]各为一个数组
    int *p[2] = {nums[0], nums[1]};
    
    //我们可以用指针数组 p 操作一个二维数组
    
    //p 为数组 p 的首地址,p[0] = nums[0] = *p,**p = nums[0][0]
    printf("nums[0][0] = %d", **p);
    
    //指针 + 整数形式,p+1 移动到 nums 的地址,*(p +1) = nums[1],则**(p + 1) = nums[1][0]
    printf("nums[1][0] = %d", **(p + 1));
    
    //先*p = nums[0],再*p + 1 = &nums[0][1],最后获取内容*(*p + 1)即为 nums[0][1]
    printf("nums[0][1] = %d", *(*p + 1));
    

    这里可能不能理解为什么*p + 1 = &nums[0][1],而不是 nums[1]。*p 获得的是一个一维数组,而 int 数组 + 1 的跨度只有 4 个字节,也就是一个单元。前面 p 是一维数组的指针,其跨度为一个数组。所以*p + 1 = &nums[0][1],而 p + 1 = nums[1]。

    四、指针与函数

    前面学习函数学到,函数参数可以为 int、char、float 等,但是在操作时,这些参数只作为形参,所有操作都只在函数体内有效(除对指针的操作外),那么今天来学习一下指针作为函数参数。

    4.1、函数参数为指针

    我们直接做一个练习,定义一个函数,用来交换两个变量的内容。

    void swap(int *x, int *y);
    void main(){
    	int x = 20, y = 10;
    	swap(&x, &y);
    	printf("x = %d, y = %d", x ,y);
    }
    void swap(int *x, int *y){
    	int t;
    	t = *x;
    	*x = *y;
    	*y = t;
    }
    

    代码非常简单,我也就不细讲了。这里传入的参数为指针,所以调用 swap 方法后 x,y 的内容发生了交换。如果直接传入 x,y,那么交换只在 swap 中有效,在 main 中并没有交换。

    4.2、函数的返回值为指针

    返回值为指针的函数声明如下:

    数据类型 *函数名(参数列表){
    	函数体
    }
    //例如:
    int s;
    int *sum(int x, int y){
    	s = x + y;
    	return &s;
    }
    

    在函数调用前要声明需要对函数声明(有点编译器不需要)

    int s;
    void mian(){
    	int *r = sum(10, 9);
    	printf("10 + 9 + %d", *r);
    }
    int *sum(int x, int y){
    	s = x + y;
    	return &s;
    }
    

    除了上面的操作,更实用的是返回一个指向数组的指针,这样就实现了返回值为数组。

    4.3、指向函数的指针

    C 语言中,函数不能嵌套定义,也不能将函数作为参数传递。但是函数有个特性,即函数名为该函数的入口地址。我们可以定义一个指针指向该地址,将指针作为参数传递。

    函数指针定义如下:

    数据类型 (*函数指针名)();
    

    函数指针在进行“*”操作时,可以理解为执行该函数。函数指针不同与数据指针,不能进行+整数操作。

    下面举个例子,来使用函数指针:

    #include <string.h>
    /**
    *	定义一个方法,传入两个字符串和一个函数指针 p,用 p 对两个字符串进行操作
    */
    void check(char *x, char *y, int (*p)());
    void main(){
    	//string.h 库中的函数,使用之前需要声明该函数。字符串比较函数
    	int strcmp();
    	char x[] = "Zack";
    	char y[] = "Rudy";
    	
    	//定义一个函数指针
    	int (*p)() = strcmp;
    
    	check(x, y, p);
    }
    void check(char *x, char *y, int (*p)()){
    	if(!(*p)(x, y)){
    		printf("相等");
    	}else{
    		printf("不相等");
    	}
    }
    

    利用函数指针调用方法具体操作如下:

    (*p)(x, y);
    

    指针除了这些地方,还在结构体中用处巨大。今天就先讲到这里~·

    展开全文
  • 运用指针,子函数,比较两个字符串是否相等相等返回1,否则返回0.求修改#include #include #include char bijiao(char a[21],char b[21]);//需要编写一个子函数可以用指针直接指向一个字符串吗?int n;main(){char...
  • C语言:比较两个字符串是否相等

    千次阅读 2021-05-18 10:06:43
    1) 使用strcmp进行比较下面通过一例子进行演示:#include #include int main(void){char* str1 = "abc";char* str2 = "abc";if (strcmp(str1, str2) == 0) {printf("str1和str2相同!\n");}else {printf("str1和str...
  • c语言指针

    2022-05-09 12:29:15
    c语言指针
  • C语言两个相同类型的结构体变量之间是可以相互直接赋值的 C语言中,在相同类型的变量间赋值时是直接内存复制的,即将他们的内存进行复制,而两个同类型的结构体变量属于同一种变量,所以赋值时是按照他们的内存分布来...
  • C语言高级-指针

    千次阅读 2022-03-12 21:34:14
    第二步:给指针变量赋值,也就是让指针指向另一个变量,当我们没有指定指针变量之前,这个指针不能被解引用; p=&a //实现指针绑定,让p指向变量a p=(int *)4 //实现指针绑定,让p指向地址为4的哪个变量 第...
  • C语言之数组指针指针数组

    千次阅读 2021-10-20 22:57:41
    为了说明这个概念,请考虑下面两个声明: int a[10]; int *b; 声明一个数组时,编译器根据声明所指定的元素数量为数组分配内存空间,然后再创建数组名,指向这段空间的起始位置。声明一个指针变量的时候,编译器只...
  • C语言指针详解

    千次阅读 2021-09-26 12:07:49
    C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每字节有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一指定数据...
  • 利用指针比较两个数组是否相等

    千次阅读 2019-02-12 16:27:18
    "您猜测的有误,两个数组不相等" endl ; return - 1 ; } p ++ ; //p右移一个单位 q ++ ; //q右移一个单位 } cout "恭喜您全部猜对yeah!" endl ; return 0 ; system ( "pause...
  • C语言指针与内存

    2022-04-09 13:57:05
    C语言指针与内存
  • ---------------------------------...先来看一下没有用到指针传递的函数: void change(int p1, int p2) { int p; p = p1; p1 = p2; p2 = p; printf("changeing.....\np1的值为:%d\n",p1); } 该函数是改变传递
  • 教你准确判断两个结构体是否相等

    千次阅读 多人点赞 2022-03-08 13:24:13
    文章目录系列文章目录前言一、判断两个结构体是否相等 前言 一、判断两个结构体是否相等 判断两个结构体是否相等:重载操作符"=="。 不能用函数memcpy来判断两个结构体是否相等:memcmp函数是逐个字节进行比较的...
  • C语言中的指针运算

    2021-05-21 01:48:00
    摘要: 指针C语言的精华、重点、难点,也是C系列语言的基础。本文介绍了C语言中的指针常量和指针变量的运算规则,以及对数组的访问。Abstract: The pointer is the essence, focus and difficult of C language ...
  • C语言如何用指针指向字符串?

    千次阅读 2020-01-30 18:13:08
    part 1 指针定义字符串 指针定义字符串,输出它的地址: #include<stdio.h> int main() { char *s1="Hello World"; char *s2="Hello World"; printf("0x%p\n",s1); printf("0x%p\n",s2); } ...
  • C语言进阶:指针的进阶

    千次阅读 多人点赞 2022-03-27 21:00:36
    指针的主题,我们在 C语言笔记:指针章节已经接触过了,我们知道了指针的概念: 1. 指针就是变量,用来存放地址,地址唯一标识一块内存空间。 2. 指针的大小是固定的4/8字节(32位平台/64位平台)。 3. 指针...
  • 指针相等时,停止字符交换。 提示 当程序中使用了指针,有比较复杂的指针表达式时,一定要清楚指针的当前值。如果初学者这把握不好,那么对指针的理解就还不够深刻。 三、空指针 这里所说的空指针,指的是指针...
  • C语言的罗盘指针——深入理解C语言指针及其应用

    千次阅读 多人点赞 2021-08-10 09:10:06
    在前面C语言的指南针——指针指针与结构体的介绍和C语言处理...C语言数组的介绍与应用篇文章中已经简要介绍了数组指针,字符串库函数和指针等内容,在这篇文章我们将继续深入了解有关字符串库函数和指针的探索。
  • C语言结构体指针强转

    千次阅读 2022-02-07 14:25:05
    C语言中结构体无法进行强转,但是结构体指针是可以进行间接强转的 eg: 先定义4结构体 typedef struct { int array[4]; }Struct_A; typedef struct { int *ptr_b; } Struct_B; typedef struct { int int1; ...
  • 函数的返回值为两个串从左至右第一个不同字符相差的acsii码的值。如果都相同返回0。 函数接口定义: 在这里描述函数接口。例如: int strmycat(char *s,char *t) 在这里解释接口参数。例如:其中s和t都是用户传入...
  • 如果两指针指向的值相等,则前一个指针进一位,后一个指针退一位,直至两个指针地址相等 定义的存放回文数的数组可以是char类型的也可以是int类型的,但int类型每个元素占4字节太浪费了,char类型每个元素只占1个。 ...
  • 语言中当比较两个对象时,必须要考虑“相等”的含义是什么,必须区分指针相等和相等性,指针相等很容易。如果现两个对象都指向相同的内存位置,则这个网对象的相等的。这里不难理解相等性,就是两个不同的对象,但是...
  • 两个指针变量可以进行的运算”

    千次阅读 2019-08-06 09:28:50
    两个指针变量不可以(A) 提供了四个选项:A.相加 B.比较 C.相减 D.指向同一地址。牛客网给出的答案A。 分析以及知识点回顾 指针变量保存的是地址,而地址本质上是一个整数,所以指针变量可以进行部分运算,例如...
  • c语言==判断字符串是否相等

    万次阅读 多人点赞 2019-08-12 18:09:24
    1、如果比的是字符串指针,有可能是相等的 2、如果比较的是字符串本身(通过*p比),只会比较第一字符 3、比较字符串数组的话,一定是不等的,*arr的话比较的是第一字符 所以还是用strcmp()吧 #include &...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,432
精华内容 14,972
关键字:

c语言两个指针相等