字符数组,字符指针,Sizeof总结

本文深入探讨了C++中字符串的存储方式及其在不同上下文中的行为差异,包括作为常量与非常量的区别、数组类型定义以及类型大小的计算方法等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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://www.cnblogs.com/JeffChen/archive/2006/05/09/395535.html

<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位系统) ``` --- ### 应用场景 - **字符数组**:需修改字符串内容或需要固定内存时(如缓冲区)。 - **字符指针**:仅需引用字符串(如函数参数传递)或动态管理内存时。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值