字符串 指针 数组
本文主要介绍下字符串、数组和指针三者在涉及互相使用时需注意的知识。
一、定义
a、字符串: 字符串我常理解为一个带‘\0’结束符的串常量,其在内存中是以顺序表的形式连续存储在内存的常量区。也可理解为以‘\0’结尾的char 数组。
b、数组: 数组作为构造数据类型的一种,其由一系列类型相同的元素组成,在内存中是以顺序表的形式存放。数组主要由两部分组成-----元素类型和元素个数,这个两个元素将决定数组在内存中占据的空间大小,该内存段的开始地址可有数组明标示出,所以数组名为一常量。
例如:char a[10],该例定义的是一个连续存储的10个char 类型的内存区域,该内存区域的开始地址由数组名‘a’可得到。
c、指针: 指针作为C语言的精髓,其是作为一个存放地址的变量,声明指针时给与的数据类型是指指针所存地址内的数据的类型。
例如:char *P, 该定义是只P指针存放char 类型的变量地址。
二、初始化
a、 字符串:字符串常量的定义是用双引号标记。例如:“abcd”,编译器会认为这是一
个字符串并在加上‘\0’字符后将其存入静态数据存储区的常量区中。在此特别注明字符串常量“abcd”其实代表了其在内存中的首地址,知道了这一点那么 char *p=“abcd”,指针赋值方式就不难理解了。
b、 指针: 指针作为存储地址常量的变量,在使用之前一定要进行初始化,不然将带
来出乎意料的后果。例如下列程序:
#include <stdio.h>
int main ()
{
char *p;
scanf("%c",p);
printf("%c",*p);
system("pause");
return 0;
}
该程序在语法上完全没有错误,但在执行时DEV C++环境下,编译器会提示进程错误。这是为什么呢?这就是指针初始化的问题。
在指针被定义时,其初值是个不确定的随机值。该值可能是内存的只读区地址(根据编译器的不同而不同),这就是进程无法进行的根源。指针一定要初始化!任何指针!切记!
指针的初始化有两种方式:
1、静态初始化(可能不专业,我自己取的名字) 如 int i; int *p=&i;
2、动态初始化,如 int *p;
p=(int *)malloc(sizeof(int));
c、 数组:数组的初始化可有两种
1、 定义时初始化 ,即:char a[]={a,b,c}或者用字符串初始化 如:char a[]=”abcd”; 对于数组的初始化需要特别指出,在自动存储类型下,如果你在定义数组时没有给数组元素赋初值,那么数组元素所表示的是个不确定值,例如:
Int a[10];
Printf(“%d”,a[1]);
该输出是&a[1] 此前被使用时所存的值。如果数组在定义只初始化了个别元素的值,则其他元素初始化为0;例如:
char p[2]={1};
printf("%d",p[1]);
该输出为0. 定义式初始化数组时,编译器支持指定初始化,例如:
int a[10]={[9]=1};
即表示a[9]=1,根据前面一原其则,其它则被初始化为0。
2、 定义以后初始化,即:
char a[2];
for(int i=0;i<2;i++)
a[i]=i;
在数组定义以外初始化数组必须借助元素下标,例如:a[i]=0;
在用字符串用如下形式初始化,则必然出错,例如;
char a[10];
a=”abcd”;
前面讲数组的定义时已讲到,数组名为一常量,它表示线性表的第一个存储位置的地址,不能对常量赋值。
可能你会问 为什么 char a[]=”abcd”,又能通过编译呢? 这还得从编译器对此条语句的执行原理说起。在定名上面数组语句是,编译为数组分配内存空间,并从静态存储区中讲字符串常量逐一拷贝到此分配的内存区间中。
三、数组、指针在对“字符串“操作的区别
该问题从下列来说明:
例一:
#include <stdio.h>
char p[] = "Hello";
int main()
{
p[0] = 'X';
printf("%s", p);
return 0;
}
例二:
#include <stdio.h>
char* p = "Hello";
int main()
{
p[0] = 'X';
printf("%s", p);
return 0;
}
例子一中,char p[] = "Hello"; 语句是数组P[]做了字符串“Hello“的拷贝,所以他可以对拷贝字符串做任意修改。
而例二中, char* p = "Hello"; 字符串常量将自己在静态存储区中的开始地址赋给了p指针,通过p指针操作的静态存储区中的字符串数据源,如果编译器有对静态存储区有保护机制的话,该类操作违法。同时,改变数据源的做法也不可取。