字符数组和字符指针

I

char sa[]="Hello World!"
char *sp ="Hello World!"

总的来说:

char sa[]="Hello World!"

//sa是个数组,sa也是一个常量指针,不能改变sa的指向,”Hello World”是数组的初始化列表,可以通过下标或者间接操作来改变值

char *sp ="Hello World!"

//sp指向字符串常量,sp是一个变量指针,可以改变sp的指向。不能通过下标或者间接操作来改变值。如果硬要改变的话是编译通过但运行出错


1、字符数组中的元素可以改变,而指针所指字符串常量的元素不可以被改变。

sa[0]='h'; //合法
sp[0]='h'; //非法

只能这样(重新改变指向)

sp = "hello world"

2、数组名sa是常量,其指向不可改变,而sp是变量,可以指向其他字符串。

sa = "Hello"; //非法
sp = "Hello"; //合法

对字符数组的赋值,要么在初始化的时候,要么就得用strcpy()

strcpy(sa, "Wang");

3、字符指针必须赋值后引用。

因为声明的时候,并不分配内存


II

还有一个知识点,就是我们知道字符数组自动在后面添加结束符‘\0’,那

么真的是

什么时候都会进行添加吗?。。。。

然而并不是!!!

1、 char str[]=”12345”; 或者 char str[]={“12345”};
这种方法定义时,系统会自动在字符串的末尾加上字符串结束符,即 ‘\0’

2、char str[10]={‘1’,’2’,’3’,’4’,’5’};这种方法定义时,系统会自动从未初始化的元素开始,将之后的元素赋为\0,如上面的数组str中的元素实际上是:’1’,’2’,’3’,’4’,’5’,’\0’,’\0’,’\0’,’\0’,’\0’

但是!!!!
!!引用char str[]={‘1’,’2’,’3’,’4’,’5’};这种方法定义时,系统不会自动在字符串的末尾加上字符串结束符;

说明分立的并且未指定大小的字符数组是不会进行添0的!


通过一段代码进行理解。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()

{

       char str1[]="12345";
       char str2[10]={'1','2','3','4','5'};
       char *str3="12345";
       char str4[]={'1','2','3','4','5',0};
       char str5[]={'1','2','3','4','5'};

       printf("%d,%d,%d,%d,%d,%d\n",str2[5],str2[6],str2[7],str2[8],str2[9],str3[4]);
       printf("各个字符串为:%s,%s,%s,%s,%s\n",str1,str2,str3,str4,str5);
       printf("各个字符串的所占的内存大小为:%d,%d,%d,%d,%d\n",sizeof(str1),sizeof(str2),sizeof(str3),sizeof(str4),sizeof(str5));
       printf("各个字符串的有效长度为:%d,%d,%d,%d,%d\n",strlen(str1),strlen(str2),strlen(str3),strlen(str4),strlen(str5));
       printf("%d\n",strcmp(str1,str3));
       printf("%d\n",strcmp(str1,str5));

}

sizeof和strlen的知识补习:
http://blog.youkuaiyun.com/21aspnet/article/details/1539951

0,0,0,0,0,53 //注意这里的53是对应的ascii
各个字符串为:12345,12345,12345,12345,1234512345
各个字符串的所占的内存大小为:6,10,4,6,5
各个字符串的有效长度为:5,5,5,5,10
0
-1

Process returned 0 (0x0)   execution time : 0.246 s
Press any key to continue.

III

参考http://www.cnblogs.com/bugman/archive/2011/09/25/2190389.html博客,有所得:

1、lvalue required as increment operand (lvalue – 左值)

关于左值和右值得问题,不再专门开篇大论了!
概括来说:
左值 - -是可以进行存储数据的地方。
右值 - -是可以表示结果值。

这个是我自己以前写的一个程序

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char len = 0;
    char str[] = "wang";
    char *p = str;

//    while(*str++ != '\0')str代表的是数组名,是不能进行++的
//    {
//        len++;
//    }
    while(*p++ != '\0')//用一个指针指向就可以了!
    {
        len++;
    }
    printf("%d", len);
    return 0;
}

当我使用注释那一段程序的时候,编译就有了lvalue required as increment operand 的error,百思不得其解。查资料方才了解到:数组名是常量指针,并不能像左值那样进行++操作!

(这也就引出了另一个知识点,指针常量和常量指针)

同时也了解到:数组名不是常量指针的情况只有两种,就是当数组名是sizeof和&的操作数时,前者产生整个数组的占用的字节数,后者产生一个指向数组的指针

2、下标引用和间接操作是一样的

 1 #include<stdio.h>
 2 int main(int argc,char **argv)
 3 {
 4     int array[]={1,2,3,4};
 5     int *b=array+1;
 6     printf("%d\n",b[1]);
 7     printf("%d\n",*(b+1));
 8     printf("%d\n",b[-1]);
 9     printf("%d\n",b[10]);
10     printf("%d\n",1[b]);
11     return 0;
12 }

输出

3
3
1
32595
3

这个例子说明了几个很有意思的事实,b是指针,但是b还是可以使用下标操作符,c在处理下标操作符时把b[1]看成*(b+1)
这也是为什么1[b]是合法的原因,1[b]被看成了*(1+b),在编译器看来b[1]和1[b]并没有区别。
并且c语言不进行下标检查,这是基于相信coder的设计思想,并且检查下标要消耗一定的资源

<think>好的,我现在需要回答用户关于字符数组字符指针在C或C++中的区别的问题。首先,我得回顾一下之前提供的引用内容,确保准确引用相关信息。用户提到了五个引用,其中提到了字符指针数组在赋值、修改内容、内存分配等方面的不同。 首先,我应该从内存分配开始。字符数组在声明时会分配固定的内存空间,而字符指针只是一个指针变量,需要指向已有的内存地址,比如字符常量或者动态分配的内存。这点在引用[3][4]中提到,字符数组可以用字符串初始化,而字符指针变量需要赋值地址。 然后是修改内容的能力。字符数组的元素可以修改,因为它们是存储在栈或静态存储区的变量。而字符指针如果指向字符常量,则内容不可修改,如引用[2][5]所述,尝试修改会导致错误。 接下来是赋值方式的不同。数组名是常量指针,不能直接赋值,而字符指针可以重新指向不同的地址。例如引用[4]中的例子,指针可以被赋值字符串的地址,但数组名不能。 可变性方面,指针变量本身的值可以改变(比如递增),而数组名是常量,不能改变。如引用[5]中的例子,s +=6是合法的,但数组名不能这样做。 还需要提到sizeof的不同,字符数组的sizeof返回整个数组的大小,而指针返回指针的大小。这点在引用中没有明确提到,但根据知识,这是常见的区别。 最后,总结两者的主要区别点,确保涵盖内存管理、修改权限、赋值、可变性、函数参数传递等方面。同时要确保使用正确的LaTeX格式,比如变量名用$符号包裹,独立公式用$$,但这里可能用不上太多数学公式,但如果有的话要注意格式。 用户可能还关心使用场景,比如何时用数组,何时用指针。例如,需要修改字符内容时用数组,而只读时用指针可能更高效。 检查是否有遗漏点,比如初始化方式,指针可以指向动态分配的内存,而数组在声明时必须确定大小。这些在引用中也有涉及,比如引用[3]提到数组字符串初始化,而指针需要赋值地址。 确保回答结构清晰,分点列出,每个区别点用加粗标题,然后详细说明,并正确标注引用来源。例如,在提到字符数组元素可修改时,引用[2][5],在提到赋值方式时引用[4][5]。 可能还需要注意术语的一致性,比如“字符指针变量”字符数组名”的区别,以及它们在操作上的限制,如++操作是否允许。 最后生成相关问题,考虑用户可能想了解的例子、常见错误、如何选择两者以及内存管理的深入问题。</think>### 字符数组字符指针的区别(C/C++) #### 1. **内存分配方式** - **字符数组**:在声明时分配固定大小的连续内存空间,可直接用字符串字面量初始化。例如: ```c char arr[] = "hello"; // 分配6字节(含'\0') ``` 数组存储在栈或静态存储区,元素可读写[^3][^4]。 - **字符指针**:仅存储地址,需指向已存在的内存(如字符常量或动态内存)。例如: ```c char *ptr = "hello"; // ptr指向常量区的字符串,内容不可修改 ``` 若指向字符常量,则内容只读;若指向动态内存(如`malloc`),则可修改[^3][^4]。 #### 2. **内容修改权限** - **字符数组**:元素是独立变量,允许修改。例如: ```c arr[0] = 'H'; // 合法操作 ``` [^2][^5] - **字符指针**:若指向常量字符串,则内容不可修改: ```c ptr[0] = 'H'; // 运行时错误(未定义行为) ``` 但若指向字符数组或动态内存,则可修改[^2][^3]。 #### 3. **赋值方式** - **字符数组**:数组名是常量指针,不可重新赋值: ```c char arr[10]; arr = "new"; // 编译错误 ``` - **字符指针**:可重新指向不同地址: ```c char *ptr; ptr = "hello"; // 合法 ptr = arr; // 合法(指向数组首地址) ``` [^4][^5] #### 4. **可变性** - **字符数组名**:是常量指针,不可自增/自减: ```c arr++; // 编译错误 ``` - **字符指针**:是变量,可改变指向: ```c ptr++; // 合法(指向下一字符) ``` [^1][^5] #### 5. **函数参数传递** - **字符数组**:传递时退化为指针,但`sizeof`在函数内部无法获取数组实际大小: ```c void func(char arr[]) { printf("%zu", sizeof(arr)); // 输出指针大小(如8字节) } ``` - **字符指针**:始终作为指针传递,行为一致[^3][^4]。 #### 6. **`sizeof`行为** - **字符数组**:返回整个数组的字节数: ```c char arr[10]; printf("%zu", sizeof(arr)); // 输出10 ``` - **字符指针**:返回指针变量的大小(通常4或8字节): ```c char *ptr; printf("%zu", sizeof(ptr)); // 输出8(64位系统) ``` --- ### 应用场景 - **字符数组**:需修改字符内容或需要固定内存时(如缓冲区)。 - **字符指针**:仅需引用字符串(如函数参数传递)或动态管理内存时。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReCclay

如果觉得不错,不妨请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值