其实呀,对于 char *p="afjfkjkladfsjije"; 这句话中的指针着实很奇怪。
当你 cout<<*p<<endl; 的时候,它输出的是那个字符串的首个字符——'a'。
当你 cout<<p<<endl; 的时候,它输出的是整个字符串的内容——""afjfkjkladfsjije""。
感觉到奇怪了吧,为什么这句话是输出整个字符串的内容,而不是地址呢。那么,我告诉你:没有为什么!
然而,经过高人指点了一下,发现是有原因的,什么原因呢?我也不太清楚,等明白了再告诉大家吧!下面补充上输出字符串指针地址的代码。
下面我就给出一段代码来验证我的说法。
#include "iostream"
#include "cstdio"
using namespace std;
int main()
{
char *p = "abckdfej";
for(int i=0; i<strlen(p); i++)
cout<<p[i]<<" "; ///其实这种输出的方式不必大惊小怪的,也就是将指针转化成了数组嘛!
cout<<endl;
cout<<endl;
while(*p) ///这种遍历的方式倒值得注意一下。
{
cout<<*p<<" ";
cout<<p<<" "; ///看到没,这里输出的是字符串的内容,不过会逐个减少,因为p++的缘故
///我将在下面一行补充上字符串指针的代码(只要将char* 转换成 void*就行了)
void *pp = p;
cout<<pp<<endl; ///看到没,这里输出的就是字符指针的地址了。
p++;
}
cout<<endl;
cout<<endl;
int a[10]={1,2,3,4,5,6,7,8,9,0};
int *intp = a;
for(int j=0; j<10; j++)
cout<<intp[j]<<" ";
cout<<endl;
while(*intp)
{
cout<<*intp<<" ";
cout<<intp<<endl; ///看到没,这里输出的是地址。之所以来一个整形的数组,就是为了和字符串做一下对比。
intp++;
}
cout<<endl;
}
设有定义字符型指针变量与字符数组的语句如下:
char *pc ,str[100];
则系统将为字符数组str分配100个字节的内存单元,用于存放100个字符。而系统只为指针变量pc分配4个存储单元,用于存放一个内存单元的地址。
(2)初始化赋值含义
字符数组与字符指针变量的初始化赋值形式相同,但其含义不同。例如:
char str[ ] ="I am a student ! " ,s[200];
char *pc="You are a student ! " ;
对于字符数组,是将字符串放到为数组分配的存储空间去,而对于字符型指针变量,是先将字符串存放到内存,然后将存放字符串的内存起始地址送到指针变量pc中。
(3)赋值方式
字符数组只能对其元素逐个赋值,而不能将字符串赋给字符数组名。对于字符指针变量,字符串地址可直接赋给字符指针变量。例如:
str="I love China! "; //字符数组名str不能直接赋值,该语句是错误的。
pc="I love China! "; //指针变量pc可以直接赋字符串地址,语句正确
(4)输入方式
可以将字符串直接输入字符数组,而不能将字符串直接输入指针变量。但可将指针变量所指字符串直接输出。
例如: cin >> str //正确
(5)值的改变
在程序执行期间,字符数组名表示的起始地址是不能改变的,而指针变量的值是可以改变的。
小结 字符数组s[100] 指针变量pc
(1)分配内存 分配100个单元 分配4个单元。
(2)赋值含义 字符串放到数组存储空间 先将字符串存放到内存
将存放串的首地址送到pc中。
(3)赋值方式 只能逐个元素赋值 串地址可赋给pc
(4)输入方式: 串直接输入字符数组 不能将字符串直接输入指针变量
(5)值的改变: 字符数组首地址不能改变 指针变量的值可以改变
1.
2.
char *ps="C Language";
可以写为:
ps="C Language";
而对数组方式:
不能写为:
而只能对字符数组的各元素逐个赋值。
当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。
一个错误的例子,如下:
但是对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。
{
}
什么是字符串常量呢?就是我们不能更改起内容的字符串。所以str1[4]='A';这样赋值就会出错。
至于为什么是运行出错而不是编译出错,我想这是编译器的问题。我用的是gcc编译器,他可能并不知道str1指向的是一个字符串常量,我们当然可以设计自己的编译器让它识别这样的错误使程序在编译时就报错
1、 字符串的表示形式
在C语言中,我们可以用两种方式访问字符串
(1) 用字符数组存放一个字符串,然后输出该字符串。
main(){
char string[]="I love China!";
printf("%s\n", string);
}
(2) 用字符指针指向一个字符串。可以不定义字符数组,而定义一个字符指针。用字符指针指向字符串中的字符。
main(){
char *string="I love China!";
printf("%s\n", string);
}
在这里,我们没有定义字符数组,而是在程序中定义了一个字符指针变量string,用字符串常量"I love China!",对它进行初始化。C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来才存放该字符串常量。对字符指针变量初始化,实际上是把字符串第1个元素的地址(即存放字符串的字符数组的首元素地址)赋给string。有人认为string是一个字符串变量,以为在定义时把"I love China!"这几个字符赋给该字符串变量,这是不对的!!
实际上,char *string="I love China!"; 等价于:
Char *string;
String = “I love China!”;
可以看到,string被定义为一个指针变量,指向字符型数据,请注意它只是指向了一个字符变量或其他字符类型数据,不能同时指向多个字符数据,更不是把“I love China!”这些字符存放到string中(指针变量只能存放地址),也不是把字符串赋给*string。只是把“I love China!”的第一个字符的地址赋给指针变量string。
在输出时,要用:printf(“%s\n”, string);,其中“%s”是输出字符串时所用的格式符,在输出项中给出字符指针变量名,则系统先输出它所指向的一个字符数据,然后自动是string加1,使之指向下一个字符,然后再输出一个字符……如此知道遇到字符串结束标志“\0”为止。
注意:可以通过字符数组名或者字符指针变量输出一个字符串。而对一个数值型数组,是不能企图用数组名输出它的全部元素的。例如:
Int i[10];
………
Printf(”%d\n”, i);
是不行的,只能逐个输出!!!!!!显然%s可以对一个字符串进行整体的输入和输出。
2、 字符串指针作函数参数
将一个字符串从一个函数传递到另外一个函数,可以用地址传递的方法,即用字符数组名作参数或用指向字符的指针变量做参数。在被调用的函数中可以改变字符串内容,在主调函数中可以得到改变了的字符串。
注意:对于实参和形参的用法,十分灵活,我们可以慢慢去熟悉它,这里列出一个表格便于大家记忆:
实参 | 形参 |
数组名 | 数组名 |
数组名 | 字符指针变量 |
字符指针变量 | 字符指针变量 |
字符指针变量 | 数组名 |