再谈一维数组、二维数组与指针、数组指针

首先看如下一下基础:

   一、int *p:p是指向一个整数变量的指针(int *p=&i    ,p指向整型变量i )

   char *p:p是指向一个字符变量的指针

 由int data[30]; int *p;有p=data;或p=&datd[1](i=0,1,2,3....)

 上面成立的原因:(1)数组名是该数组首元素的地址

                        (2)&data表示取整个数组的地址,包括多维数组。&data[0]取数组首个元素的地址。单独data则亦表示数  组首元素的地址。

                         (3)p是p是指向一个整数变量的指针

     二、 int a[3][4];a是指向由4个int数据构成的数组的指针

            int (*p)[4];p是指向由4个int数据构成的数组的指针

      于是必然有:p=a;

      分析二成立的原因:1、c primer plus中对二维数组和数组指针的定义即是上面的方式;

                                2、因为在数组与指针中有p[m]=*(p+m)的关系。直接将上面的数组指针int (*p)[4];改写

成int (*p+0)[4];即等效于int p[0][4];自然可以很清晰的理解了。

      三、字符的存储形式:每个字符以整数的形式储存。

            字符串的储存方式:一“”结尾的char数组。

     四、c语言中字符串,就是字符数组,故指针访问字符串即等效于指针访问数组元素。

      1)、数组与数组,数组与指针,指针与指针之间的赋值

       数组之间是不可以直接赋值的,要直接赋值的话,也只能是利用循环,一个一个的赋值:

 #include<stdio.h>
int main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
int b[10]={1,2,3,4,5,6,7,8,9,10};
for(int i = 0;i<10;i++)

{
a[i]=b[i];       (可以为*(a+i) = *(b+i) )
}
return 0;
}

当然还可以通过其他方法来实现,比如取地址运算,把数组a的首地址赋给B数组,不过这要通过指针来实现:

#include<stdio.h>
int main()
{
int k;
char *s[]={"you","are","the","one"};
char **q;
for(k=0;k<4;k++)
{
  *q[k]=*s[k];
  printf("%s ",*q[k]);
}
}

还有一种简单点的方法就是拷贝运算,你可以利用c语言库里面已经定义好的函数直接实现你所要实现的功能,实现方法如下:

#include <string.h>
#include <stdio.h>
void main()
{
char a[10]={"asdsadsa"},b[10];
strcpy(b,a);
printf("%s ",b);
}

   五、两个指针之间的赋值则就是根据数组间的赋值就可以了,只需利用( a[i] = *(a+i) ,i=0,1,2,3,4.....)

   六、指针字符与字符数组之间的关系 

        采用指针存储字符串,其实质就是把字符串的首地值附给基类型为char的指针变量,从而可以从字符串首元素开始对字符串进行操作,但是,,这里面也存在一点问题,如下:    
        int main()
         {
            char *p="hello";
            p[0]='M';
            printf("%s ",p);
            return 0;
          }
     运行结果会出现断错误,原因在于,*p="hello" 这句仅仅声明了一个指针变量,指向字符串"hello ",而"hello "这个字符串程序没有给它分配空间,编译器把它分配到常量区.而常量字符串的值是不允许被修改的 ,所以会出现断错误.
 
 
       程序改为如下就正确了
        int main()
        {
           char p[12]="hello";
           char *p1=p;
           p1[0]='M';
           printf("%s ",p1);
           return 0;
        }   
     
      因为,p[12]="hello "是你自己定义的一个长度为12 的字符数组,所以字符串"hello world"编译器会给它分配空间(在栈中及非常量区),所以可以修改它的值. 
字符串“hello”本身就是一个常量字符指针,而对于指针p,无非就是一个地址的拷贝,也就是“hello”地址的拷贝,相当于p指向一个字符串常量,字符串常量是不予许改变的!
而对于p[]来说就不一样了,虽然hello本身是常量,不过此时拷贝给p[]的不是地址,而是内容,也就是“hello”,也就是p本身拥有一个自己的hello副本,可以对其进行想要的合法操作,比如改变等.
 
最后说明:
c语言中,不能对字符指针变量指向的字符串再赋值,这不是绝对正确的:当指针指向的字符串是常字符串时当然不能再赋值,因为目标是“常量”,而当指针指向的字符串不是常字符串时就可以再赋值,比如用动态申请内存方法创建的字符串。具体说就是用char *p="abcqer12345";这种方法定义字符串是不能通过指针改变内容的,原因是这个定义确定了abcqer12345是字符串常量——因为char *p="abcqer12345";被编译器解释为“创建一个字符串常量abcqer12345,并把它的首地址(就是a的地址)赋给char *型指针p。
 而如果用动态申请内存时基本方式如下:
在C语言中,动态申请内存可以用stdlib.h中声明的malloc函数。

函数原型:

void *malloc(unsigned int num_bytes);

num_bytes为要申请的内存数量。申请成功,则返回指向这块内存的指针;失败则返回NULL。

申请成功之后,就可以使用gets来接收字符串。代码如下:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int size = 100;
    char *str;
    
    str = malloc(size);
    gets(str);
    puts(str);
    free(str);
    
    return 0;
}
 
   七、 补充知识:指针

   指针在定义后必须要先初始化才能使用,因为未初始化的指针指向哪里,根本就不知道,使用后结果不可预知,如果指向的内存中比较重要的地方,可能会导致系统异常,如提示指向了一个不可用的地址之类。

   对指针进行初始化,有三种方法:

  1. 运用int *p=0;这个语句老老实实的将指针初始化了;
  2. 把int *p=0和p=&i这两句话连成一句话: int *p=&i(&i可以用a,当a表示已定义的数组或已有所指的指针等);这样,就既把指针变量p初始化了,又把它指向了某个值;
  3. 用常量来初始化一个指针。则需用强制类型转换,找一个内存地址,即(ElementType *) 来把常量转换成内存中的一个地址。既采用:
ElementType *p=(ElementType *)[常量]
原文地址:https://www.cnblogs.com/wgang171412/p/5125348.html