c语言char []和char *的区别

作者: CodingCode | 来源:发表于2017-05-14 16:39 被阅读350次

招聘程序员面试中经常碰到分不清char *和char []区别的候选者,统一认为他们不都是字符串吗?特别是近年刚毕业的学生,甚至有些还是计算机科班毕业生也解释不太清楚。

究其原因计算机高级语言的发展已经屏蔽了计算机内部的实现模型,甚至不需要理解冯-诺伊曼计算机体系结构,也能成为一名优秀的"程序员"。


说远了,简单的说,这两者的区别是:

  1. char []定义的是一个字符数组,注意强调是数组
  2. char * 定义的是一个字符串指针,注意强调是指针

数组表示字符串数组,数组的每一个元素都是一个字符,修改一个数组指的是修改数组的值,即改变其中一个或者多个元素的值;而指针表示这是一个地址,其值就是一个地址,并没有字符串值的概念,修改一个指针只是把指针指向别的地址或者NULL;


看代码例子: 全局变量
定义全局数组变量ch1和字符串指针ch2。

1   char ch1[] = "ABCDEFGH";
2   char * ch2 = "abcdefgh";

(在Linux x64 gcc-4.4环境下验证, 下同)
生产的汇编码如下:

.globl ch1
    .data
    .type   ch1, @object
    .size   ch1, 9
ch1:
    .string "ABCDEFGH"
.globl ch2
    .section    .rodata
.LC0:
    .string "abcdefgh"
    .data
    .align 8
    .type   ch2, @object
    .size   ch2, 8
ch2:
    .quad   .LC0

可以看到:

  1. 变量ch1定义在data段中,大小是9字节,其值是"ABCDEFGH"字符串内容(字符串长度8加上最后一个结尾'\0')。
  2. 变量ch2定义在rodata段中,大小是8字节,其值是.LC0的地址值,注意这个大小8不是字符串中含有8个字符,而是x64下的指针地址长度;如果把字符串长度改为"abcd"4个字符,这儿大小还是8字节。

这里就可以看出ch1的内容可以被修改,而ch2不能被修改;因为ch1的内容在数据段中,而ch2的内容在只读段中。


在看代码例子: 函数变量
定义函数内部数组变量ch1和字符串指针ch2。

int foo() {
    char ch1[] = "ABCDEHGF";
    char * ch2 = "abcdefgh";
    return 0;
}

生成汇编码如下:

    .section    .rodata
.LC0:
    .string "abcdefgh"
    .text
.globl foo
    .type   foo, @function
foo:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $1145258561, -32(%rbp)
    movl    $1212630597, -28(%rbp)
    movb    $0, -24(%rbp)
    movq    $.LC0, -8(%rbp)
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   foo, .-foo

看处理ch1的这几条指令

movl    $1145258561, -32(%rbp)
movl    $1212630597, -28(%rbp)
movb    $0, -24(%rbp)

$1145258561 = 0x44434241 = 'DCBA'
$1212630597 = 0x48474645 = 'HGFE'
字符串"ABCDEFGH"直接按照值写进函数栈里面。

在看处理ch2的一条指令

movq    $.LC0, -8(%rbp)

.LC0是定义在只读数据段中的字符串地址,上述指令把.LC0的地址写进函数栈中,而并没有把.LC0的内容写进函数栈中。
可见函数foo的栈中存储了"ABCDEFGH"的内容和"abcdefgh"的地址。

由此可见两者的取别:

  1. ch1的内容存储在函数栈中,可以被修改,函数一旦返回空间就被释放。
  2. ch2的内容保存在只读数据段中,不可被修改,其空间不会被释放。

总结一下,回到开头提到的:

  1. ch1强调的是数组,ch2强调是指针,在各自作用域范围内有效,可操作。
  2. 作为数组可以操作的是数组值,那么数组内容是可以改变的。
  3. 作为指针可以操作的是指针值,那么指针内容是可以改变的,即指向另一个地址,但不能改变指针指向的内容。换句话说就是可以修改指针的值,但不能修改指针值的值。

相关文章

  • c语言char []和char *的区别

    招聘程序员面试中经常碰到分不清char *和char []区别的候选者,统一认为他们不都是字符串吗?特别是近年刚毕...

  • c语言 char *和char[]的区别

    最近复习了下c语言,以前学习它只是为了应付考试,现在重新学习下,写写文章只是想着,哪天年龄大了,忘记了,再回头来翻...

  • char* he char [] 的区别

    [C] char a[] 和 char *p 的区别 原文:https://blog.csdn.net/ftell...

  • char * 和char[]的区别

    如下代码块char pngPath[10]; 在下面的sprintf函数中报错了但是char *pngPath可...

  • char * 和 char []的区别

    区别: 1:char* s1=”abc”;s1是一个指针,s1所指向的地址的内容是不可改变的,但是s1可以指向其他...

  • Redis底层数据结构SDS

    前言 Redis是C语言开发的,C语言的字符类型是char,字符数组是char[],Redis没有直接使用C语言的...

  • signed char和unsigned char的区别

    很多人在写c语言程序的时候,经常分不清两者的区别,到底该定义signed char还是unsigned char呢...

  • 字符串反转

    char类型只能存储单个字符,在C中要存储多个字符组成的字符串得用char*或char[]。区别是char*保存的...

  • 嵌入式学习笔记19.11.27

    c语言共用体: #include union st{ int x; char a; char s[10]; }st...

  • C | char* and char[]

    char[] 就是普普通通的字符数组char* 却是王子一般的字符指针你如果把一个字符串赋值给char* 类型的...

网友评论

    本文标题:c语言char []和char *的区别

    本文链接:https://www.haomeiwen.com/subject/scuqxxtx.html