您的位置:首页 > 编程语言 > C语言/C++

C/C++中字符指针和字符数组

2014-10-08 11:00 253 查看
转载自

char* s1="hello";
char  s2[]="world";
 
第一个是字符串常量,是只读的, 不可以修改。

第二个是字符数组,每个字符都有一个独立的地址。

 
char* test(){
char ch[5]="hi";//gcc 会警告:返回局部变量。
return ch;

这个函数是错误的,因为字符数组ch是局部变量,当test调用结束是占用的空间将被释放。
在函数中声明固定大小的数组会在函数调用完成后释放掉内存。
要想不释放,就要在堆上声明,如下:
 
 
数组作函数形参:
“作为函数参数的数组名”等同于指针——《C专家编程》
把数组作为参数传递给函数时,并非把整个数组传递进去,此时数组退化为一个同类型的指针——《高质量C/C++》
为什么这么做?
a)数组在内存中连续存放,只传递数组名指针也可以访问整个数组。
b)全部传递开销太大,如果把整个数组元素都传递进去,不仅需要大量的时间拷贝数组,也将占用大量的堆栈空间,我们知道堆栈空间是有限的。
 
---------------------------------------------------------------------------------------------------------------------
 
以下为转载,转自:http://www.cnblogs.com/8586/archive/2009/05/22/1487371.html
 

1.以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写

  "abc",那么编译器帮你存储的是"abc/0"

2."abc"是常量吗?答案是有时是,有时不是。

  不是常量的情况:"abc"作为字符数组初始值的时候就不是,如

                  char str[] = "abc";

    因为定义的是一个字符数组,所以就相当于定义了一些空间来存放"abc",而又因为

    字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为

    char str[3] = {'a','b','c'};

                  又根据上面的总结1,所以char str[] = "abc";的最终结果是

    char str[4] = {'a','b','c','/0'};

    做一下扩展,如果char str[] = "abc";是在函数内部写的话,那么这里

    的"abc/0"因为不是常量,所以应该被放在栈上。

  

  是常量的情况:  把"abc"赋给一个字符指针变量时,如

                  char* ptr = "abc";

    因为定义的是一个普通指针,并没有定义空间来存放"abc",所以编译器得帮我们

    找地方来放"abc",显然,把这里的"abc"当成常量并把它放到程序的常量区是编译器

    最合适的选择。所以尽管ptr的类型不是const char*,并且ptr[0] = 'x';也能编译

    通过,但是执行ptr[0] = 'x';就会发生运行时异常,因为这个语句试图去修改程序

    常量区中的东西。

    记得哪本书中曾经说过char* ptr = "abc";这种写法原来在c++标准中是不允许的,

    但是因为这种写法在c中实在是太多了,为了兼容c,不允许也得允许。虽然允许,

    但是建议的写法应该是const char* ptr = "abc";这样如果后面写ptr[0] = 'x'的

    话编译器就不会让它编译通过,也就避免了上面说的运行时异常。

    又扩展一下,如果char* ptr = "abc";写在函数体内,那么虽然这里的"abc/0"被

    放在常量区中,但是ptr本身只是一个普通的指针变量,所以ptr是被放在栈上的,

    只不过是它所指向的东西被放在常量区罢了。

3.数组的类型是由该数组所存放的东西的类型以及数组本身的大小决定的。

  如char s1[3]和char s2[4],s1的类型就是char[3],s2的类型就是char[4],

  也就是说尽管s1和s2都是字符数组,但两者的类型却是不同的。

4.字符串常量的类型可以理解为相应字符常量数组的类型,

  如"abcdef"的类型就可以看成是const char[7]

5.sizeof是用来求类型的字节数的。如int a;那么无论sizeof(int)或者是sizeof(a)都

  是等于4,因为sizeof(a)其实就是sizeof(type of a)

6.对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通

  的指针类型,如对于void func(char sa[100],int ia[20],char *p)

  则sa的类型为char*,ia的类型为int*,p的类型为char*

7.根据上面的总结,来实战一下:

  对于char str[] = "abcdef";就有sizeof(str) == 7,因为str的类型是char[7],

  也有sizeof("abcdef") == 7,因为"abcdef"的类型是const char[7]。

  对于char *ptr = "abcdef";就有sizeof(ptr) == 4,因为ptr的类型是char*。

  对于char str2[10] = "abcdef";就有sizeof(str2) == 10,因为str2的类型是char[10]。

  对于void func(char sa[100],int ia[20],char *p);

  就有sizeof(sa) == sizeof(ia) == sizeof(p) == 4,

  因为sa的类型是char*,ia的类型是int*,p的类型是char*。

 

--------------------------------------------------------------------------------------------------------------

 

以下为转载,转自:http://blog.csdn.net/shineHoo/archive/2010/08/19/5823756.aspx

 

C语言中没有专门的字符串变量,如果要将一个字符串存放在变量中,必须使用字符数组,即用一个字符型数组来存放一个字符串,数组中每一个元素存放一个字符。

<1> 定义: char c[10]

字符型与整型互相通用,因此 int c[10] 也可以定义字符数组。但由于两种类型分配字节不同, 用整型来定义会浪费空间, 另外这样定义实际意义也不大, 只是为了说明其合法性。

<2> 初始化: 

    最简单的方法即逐个赋值: char c[10]={'I', ' ', 'a', 'm', ' ', 'h', 'a', 'p', 'p', 'y'}; 10个字符分别赋绐c[0]到c[9]10个元素。

    如果初值个数小于数组长度,则只将这些字符赋绐数组中前面的元素,其余元素自动定为空字符(即'/0')。
    如char c[12]={'I', ' ', 'a', 'm', ' ', 'h', 'a', 'p', 'p', 'y'}; 则c[10]、c[11]值都为'/0' 。

    C语言中,将字符串作为字符数组来处理。一般我们用字符数组来存放字符串时,都要先确定一个足够大的数组,而实际并用不了那么多,而我们只关心其有效位,为测定字符串实际长度,C规定了一个"字符串结束标志",以字符 '/0' 代表。如果有一个字符串,其中第10个字符为'/0',则此字符串的有效字符为9个。也就是说,在遇到字符'/0'时,表示字符串结束,由它前面的字符组成字符串。

    系统对字符串常量也自动加一个'/0'作为结束符。

    对于语句: pirntf("How do you do? /n"); 实际上该字符串在内存中存放时,系统自动在最后一个字符'/0'的后面加了一个'/0'作为字符串结束标志,在执行printf函数时,每输出一个字符检查一次,看下一个字符是否'/0'。遇'/0'就停止输出。

    可以用字符串常量来初始化字符数组。如:

    char c[]={"I am happy"};

    也可直接写成:

    char c[]="I am happy"; 注意此时数组的长度不是10,而是11,因为系统自动加上了'/0'结束符。

    字符数组不要求最后一个字符为'/0',而为了使处理字符数组和字符串的方法一致,便于测定字符串的实际长度,能及方便在程序中处理, 在字符数组末尾也常加上一个'/0'。

<3> 字符数组的输入输出 

    (1) 逐个字符输入输出。用格式符"%c"输入或输出一个字符。

    (2) 将整个字符串一次输入或输出。用"%S"格式符,意思是输出字符串(String)。例如:

  char c[]={"china"};

  printf("%S", c);

如果一个字符数组中包含一个以上'/0',则遇第一个'/0'时输出就结束。

    (3) 若输入字符串长度超过字符数组所定义的长度时,将造成数组下标越界,但系统对此并不报错。

    (4) 用%S格式输入字符时,遇空格、Tab键和回车将自动结束输入。

用scanf函数输入时, 遇到空格则认为一个字符串结束。试验如下:

#include <stdio.h>

int main()

{

    char str1[5], str2[5], str3[5];

    scanf("%s %s %s", str1, str2, str3);

    printf("%s %s %s/n", str1, str2, str3);

    return 0;

}

运行结果:

================================

how are you↙

how are you

================================

#include <stdio.h>

int main()

{

    char str[13];

    scanf("%s", str); /* 注意输入项为数组名,而非 &str */

    printf("%s/n", str);

    return 0;

}

运行结果:

================================

how are you?↙

how

================================

由第二个程序可知,实际并未将这12个字符加上'/0'送到数组str中,而是将空格前的字符"how"送到str中,将其视为字符串处理,在其后加上'/0' 。

 

char *a = new char[5];
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: