码迷,mamicode.com
首页 > 其他好文 > 详细

[C]char*和char[]的区别

时间:2020-08-29 15:31:24      阅读:52      评论:0      收藏:0      [点我收藏+]

标签:har   rest   函数   file   参数声明   style   http   targe   xxxxxx   

一、概述

在偶然一次尝试使用unix函数mkdtemp的时候发现一个问题,函数有一个唯一参数template是一个字符串指针,它的声明如下:

char *mkdtemp(char *template);

但是,当我声明一个指针形式的字符串指针,并传入mkdtemp的时候,出现了Segmentation fault的报错,代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    char *path = "/documents/temp_XXXXXX";
    printf("mkdtemp: %s\n", mkdtemp(path));
}

如果把声明改成字符串数组的形式,代码则可以顺利运行:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    char path[] = "/documents/temp_XXXXXX";
    printf("mkdtemp: %s\n", mkdtemp(path));
}

二、原因

通过百度发现了一篇这样的文章:char*和char[]的区别

这篇文章的开头有一段关于进程内存空间分配的描述;

接下来是一段程序,每个声明都标明了程序会在哪个内存段保存变量或常量:

//main.cpp
int a=0;    //全局初始化区
char *p1;   //全局未初始化区
main()
{
   int b;栈
   char s[]="abc";   //
   char *p2;         //
   char *p3="123456";   //123456\0在常量区,p3在栈上。
   static int c=0//全局(静态)初始化区
   p1 = (char*)malloc(10);
   p2 = (char*)malloc(20);   //分配得来得10和20字节的区域就在堆区。
   strcpy(p1,"123456");   //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成一个

地方。
}

看到对于p3的描述,就能猜测到问题出在哪里了:

p3保存的是指向常量区的内存空间,这段内存是不可以修改的。

再来看看mkdtemp的描述:

mkdtemp传入一个字符串路径,这个字符串路径必须以XXXXXX结尾,返回一个字符串路径,这个字符串后6位XXXXXX字符被替换成了在这个路径下唯一的值(因为它在这个路径下是唯一的,所以相对于整个文件系统来说也是唯一的)

猜测是函数通过修改传入的字符串内存空间,然后返回指向该内存空间的指针,由于用字符串常量声明的字符串指针path指向的是字符串常量空间,空间不可以被修改,所以程序报错了。

为了证实这个猜想,打印一下path的值和mkdtemp返回的值就行了:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
    char path[] = "/documents/temp_XXXXXX";
    printf("ptr addr with stack: %p\n", path);
    printf("ptr addr by mkdtemp return: %p\n", mkdtemp(path));
}

结果:

ptr addr with stack: 0x7fffa7440a00
ptr addr by mkdtemp return: 0x7fffa7440a00

看吧,一模一样的;

 

三、解决方法

遇到需要修改指向空间的函数,用栈空间或堆空间。

其实,通常看函数声明就知道这个函数内部需不需要修改参数指针指向的空间;

就好像mkdtemp一样,需要修改参数指针指向空间的参数声明是不带类型限定符const的:

char *mkdtemp(char *template);

而不需要改变参数指针指向空间的函数参数通常会声明成这个样子:

FILE *fmemopen(void *restrict buf, size_t size,const char *restrict type);

type参数被声明成了常量,所以可以放心把字符串写在只读区;

四、相关文献

在《C语言核心技术》的"第三章 常量 字符串常量"最后一段中提到这个问题;

在《Unix高级环境编程》的第 5.13 小节的最后也有一个这个问题的示例和说明;

[C]char*和char[]的区别

标签:har   rest   函数   file   参数声明   style   http   targe   xxxxxx   

原文地址:https://www.cnblogs.com/yiyide266/p/13555852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!