数组, 指针以及数组指针和指针数组,指针常量,常量指针

目录

一、数组和指针

1、指针和数组的关系

二、数组指针和指针数组

1、数组指针 

2、指针数组 

三、char *p 和char q[]的区别:

1.区别一 

2.区别二

四、指针常量和常量指针

1.指针常量

  2.常量指针

  3.总结  


一、数组和指针

1、指针和数组的关系

下面是一个数组int a[2][3]:

(a),(a+1)的指向如图所示:即(a),(a+1)指向的是int [3],也就是说他们是行地址

 

所以对于int *p ,要使的指针能够指向数组,可以使用如下方式:

        p = *a;                    这里的*a就是列地址)

        p = &a[0][0];         (*a == &a[0][0])

        p = *(a+0);             (*(a+0) == *a == &a[0][0])

//通过这三种方式使得指针指向数组a,之后变可以向后移动指针来获得数组内容,即可以理解二维数组a是一个一维数组p[6]。

例如使用 :

a[2][3] = {{1,2,3},{2,3,4}};
int *p = *a;
int i = 0;
for(i = 0; i < 6; i++){

    printf("%d",p[i]);
}

二、数组指针和指针数组

1、数组指针 

        除了使用上述的方式,可以使用数组指针来指向a。即用行地址来指向a。

        数组指针的定义为: 数据类型 (*指针 [index])= value  相当于 数据类型[index] *p = value.

所以可以使用(注意p是变量,a相当于常量,所以不能给a赋值,在其他方面p相当于a使用)

int (*p)[3] = a;来指向a;

下面是数组指针的两个例子:

例1:

//连接前面的代码

int (*p)[3] = a;

int j = 0;
for(i = 0; i < 2; i++){
    for(j = 0; j < 3; j++){
        printf("%d",*(*(p+i)+j));
    }
}

例2:

int main()
{
    char s[6][5] = {{"ll"}, {"jj"}, {"fk"},{"lsdf"}, {"fjsl"},{"sdjf"}};
    char (*ptr)[5] = s;
    
    int i ;

    for(i = 0; i < 6; i++){
        printf("%s\n", ptr[i]);
    }
}

2、指针数组 

例如:char *ptr[6],下面是他的使用

int main()
{
    char s[6][5] = {{"lddd"}, {"jj"}, {"fk"},{"lsdf"}, {"fjsl"},{"sdjf"}}; 
    char *ptr[6];
    int i;
    for(i = 0; i < 6; i++){
        ptr[i] = s[i];
    }
    for(i = 0; i < 6; i++){
        printf("%s\n", ptr[i]);
    }

}

三、char *p 和char q[]的区别:

1.区别一 

        所以在使用sizeof的时候需要注意sizeof(p) 和sizeof(q)的结果不同,sizeof(p) 的值是char *指针大小,64位机为8,而sizeof(q)就是字符串大小(包括‘\0')。

我认为要明白这两个的区别还是需要自己在电脑上实验一下,例如这样

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *p = {"kdfj"};
    char q[7] = {"jjdkj"};


    printf("%ld  %ld  %ld\n", sizeof(p), sizeof(*p), strlen(p));

    printf("%ld  %ld  %ld\n", sizeof(q), sizeof(*q), strlen(q));
    return 0;
}

你将看到如下结果:

 在写这个例子的时候,我在想sizeof 和strlen 函数在计算字符串大小时候的使用,一个众所周知的区别是是否计算   '\0'  ,然后我进行了下面的测试:

printf("%ld  %ld\n", sizeof("dls"), strlen("dls"));

我在前面的测试中用过sizeof  和 strlen 计算字符串大小,但是为什么还要这样做呢?

就是为了体会一下sizeof 在计算这四种情况的区别:

        char p[4] = {"ld"},        sizeof(p) = 4;  他就该是四,因为你请求的指针常量大小就是4,

                                           不是 够 就加 '\0'.  他本质是个常量,你不能用p[0] = a,来改变他的值。

        char p[4] = {"lll"},         sizof(p) = 4;

        char p[4] = {"dlsl"},      sizeof(p) = 4;  这里没有计算 '\0' 因为他没有。

        "dls" ,                        sizeof("dls");   sizeof ("dls") = 4;

第三种情况,我有个疑问,到底这样做否会有问题呢?因为他没有 ’\0' 结束,所以我进行了如下的测试:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *p = {"kdfj"};
    char q[7] = {"jjdkj"};


    // printf("%ld  %ld  %ld\n", sizeof(p), sizeof(*p), strlen(p));

    // printf("%ld  %ld  %ld\n", sizeof(q), sizeof(*q), strlen(q));

    // printf("%ld  %ld\n", sizeof("dls"), strlen("dls"));

    char l[4] = {"llfd"};
    int i;
    for(i = 0; i < 6; i++){
        if(l[i] != '\0')
            printf("l[%d]: %c\n", i, l[i]);
        // else{
        //     break;
        // }
    }

    char t[4] = {"ld"};
    for(i = 0; i < 6; i++){
        if(t[i] != '\0')
            printf("t[%d]: %c\n", i, t[i]);
        // else
        // {
        //     break;
        // }
    }
    return 0;
}

 对的你没有看错,我越界访问了,我就是想这么做,来看看他有什么问题:

 可以看到 t[4] 他有 '\0'  因为t[2] t[3]没有输出。而  l[4] 的问题就很明显,他没有 '\0', 如果打开 else语句,你可以看到如下的输出:

 对的没错, 我想表达的就是不要这样用 l[4] = {"lsld"}; 还是有个 '\0' 好。

2.区别二

要记住,对于 char *p =  {”ls"}, {”ls"}是一个常量,常量的值是不可以改变的,但是指针变量指向是可以改变的,但是这样p[0] = 'a'会报错,因为你在修改那个常量。

对于 char q[4] = {"fd"}; 你就可以这样改 q[0] = 'b';

为此 我进行了如下的测试:

int main()
{
    char *t = {"dkk"};
    char *p = {"kdfj"};
    char q[7] = {"jjdkj"};
    printf("*p= %s\n", p);
    printf("*q = %s\n", q);


    //p[0] = 'a';   //报错  试图修改常量的值   
    p = t;
    q[0] = 'b';     //这个就可以, q 是指针常量,对,q自己是常量,
                    //那么他指向的空间不能改变,但是内容可以改变

    //q = t;          //报错, 表达式必须是可修改的左值, q是常量当然不可修改
    printf("*p= %s\n", p);
    printf("*q = %s\n", q);
}

 结果如下:

好了这个时候我又有了这样的疑问: 

1 .怎么char *p = {"kdfj"}中,{"kdfj"}不可修改

2,但是char q[7] = {"jjdkj"}中,{"jjdkj"}可以修改呢?

以前我学习c的时候,老是会看到有人说  ={” jd“} 是个字符串常量,那时候我还没有仔细的观察, 直到现在,我好像有点明白了, 对于 ={"dkfj"},你要怎么看他,要看你是怎么定义的,就是你要看你的左值写的是什么,对于1来说他是字符串常量,对于2来说他是字符串,也是个变量。

四、指针常量和常量指针

1.指针常量

int *const p;

 从前往后读,就是指针常量,但是重点在最后,他是一个常量;我的理解是,我们定义了一个常量,他是指针类型的,那么常量必须在定义的时候就初始化,例如我给他初始化为s;之后常量的值就不可以改变了,它一值指向s,但是呢,我们可以通过*p来修改他所指向内容的值。

int main()
{
    char s[] = {"lslslslsjfjf"};
    char t[] = {"jiawenshi"};
    char * const p = s;
    printf("p = %s\n", p);
    p[1] = 'u';
    printf("p = %s\n", p);
    p = t;      //报错
    printf("p = %s\n", p);
    return 0;
}

  2.常量指针

  这里定义了常量指针 const char *p,或者可以这样定义:char const *p;读的时候从前往后读,就是常量指针。按照前面的理解就是他是一个指针,然后指向一个常量。也是一样的理解重点在指针,那么指针的值是可以改变的,但是所指向的常量值是不可以改变的。

int main()
{
    char s[] = {"lslslslsjfjf"};
    char t[] = {"jiawenshi"};
    const char *p = s;        // char const *p = s;
    // printf("p = %s\n", p);
    // p[1] = 'u';   //报错
    printf("p = %s\n", p);
    p = t;      
    printf("p = %s\n", p);
    return 0;
}

  3.总结  

                我在网上看到有的人的定义完全相反,其实我觉的没有什么太大的关系,只要记住" * "和 const谁更靠近p就可以决定哪个能改哪个不能改。

下面是一些参考,不过我认为我写的挺详细的:

 char * 与char []区别总结_char*_bitcarmanlee的博客-CSDN博客

 C语言 char*和char[]用法_c char*_imxlw00的博客-CSDN博客

 如果你觉得我写的有问题,欢迎你与我交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值