本文转自 CSDN 博客http://blog.csdn.net/okliujieko/article/details/6821321,
代码部分略作修改,从C++ 转成 C;修改了原文中的错别字;增加部分内容
用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的。在使用时应注意以下几个问题:
- 1.字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。
2、对字符串指针方式
char *ps=”C Language”;
可以写为:
char *ps;
ps=”C Language”;
而对数组方式:
static char st[]={"C Language"};
不能写为:
char st[20];
st={"C Language"};
只能对字符数组的各元素逐个赋值,如下:
1 | strcpy(st,"C Language"); |
从以上几点可以看出字符串指针变量与字符数组在使用时的区别,同时也可看出使用指针变量更加方便。
当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。
一个错误的例子,如下:
char *name;
scanf("%s",name);
printf("%s",name);
有的编译器虽然也能通过,但这是错误的,因为这个指针,定义时指向了不可用的地址。解决这个问题有两种方法:用数组的方式或给字符串分配内存空间的方法。
数组的方法:
char name[20];
scanf(“%s”,name);
printf(“%s”,name);
给字符针针分配内存空间的办法:
char *name;
name=(char*)malloc(50); //此时name已经指向一个刚刚分配的地址空间。
scanf("%s",name);
printf("%s",name);
但是对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。
- 3、int main()
1 | { |
数组和指针都可以在它们的定义中用字符串常量进行初始化,尽管看上去一样,底层的实现机制却不相同。
定义指针时,编译器并不为指针所指向的对象分配空间,它只是分配指针本身的空间,除非在定义的同时赋值给指针一个字符串常量进行初始化。例如:下面的定义创建了一个字符串常量(为其分配了内存):
char *p="abcdefg";
注意只有对字符串常量才是如此,不能指望为浮点数之类的常量分配空间,如:
Float *p=3.14; /*错误,无法通过编译*/
下面结合一个实例谈谈初始化指针时创建的字符串常量与数组中的字符串的区别:
在ANSI C中,初始化指针时所创建的字符串常量被定义为只读。如果试图通过指针修改这个字符串的值,程序就会出现未定义的行为。在有些编译器中,字符串常量被存放在只允许读取的文本段中,以防止它被修改。
数组也可以用字符串常量进行初始化:
Char a[]="abcdefg";
与指针相反,由字符串常量初始化的数组是可以修改的。其中的单个字符在以后可以改变。原因在于,字符串常量在编译后存储在常量区,在嵌入式系统,例如ARM cortex-m4类似的芯片中,常量存放在 flash 区域,是只读的。桌面系统与之类似,会将字符串常量存放在.text段,也是只读的。在使用字符串指针时,仅在 RAM 中分配一个指针的空间,之后将指针指向字符串常量的地址。而如果是字符串数组,则会在 RAM 中分配数组所需的空间,初始化字符串数据时,会将字符串常量从 flash 拷贝一份到 RAM 空间,因此是数组内容是可更改的。
下面是一个在vc6中的一个例子,完成将一个字符串中的所有大写字母全部转换为小写字母的功能:
#include <stdio.h>
#include <ctype.h>
int strlower(char *string)
{
if(string==NULL)
{
return -1;
}
while(*string)
{
if(isupper(*string))
*string=tolower(*string);
string++;
}
*string='\0';
return 0;
}
void main()
{
char *test=”ABCDEFGhijklmN”;
strlower(test);
printf(“%s”,test);
}
其中,如果采用char *test=”ABCDEFGhijklmN”;会产生运行时错误。Char test[]=”ABCDEFGhijklmN”则程序正常运行,原因如前所述。
原文链接:本人CSDN博客