`
蒙面考拉
  • 浏览: 160555 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

char *p,char p[]以及string p的区别

 
阅读更多

问题的引入:

 

     char a[]=" abc " ;  

     char b[]=" abc " ;

     char *c=" abc " ;

     char *d=" abc " ;

     const char e[]=" abc " ;

     const char f[]=" abc " ;

     const char *g=" abc " ;

     const char *h=" abc " ;

     printf(" %i\n " ,a==b);

     printf(" %i\n " ,c==d);

     printf(" %i\n " ,e==f);

     printf(" %i\n " ,g==h);

 

 

正确的答案:0 1 0 1。

 

说明:指针不分配所指向的数据的空间,数组分配所有元素的内存空间。

            char *c="abc"; 这是定义一个指针,并把常量区的一个字符串“abc”的首地址赋值给这个指针,所以,是无法修改数据

            内容的(*p='h',错!),但是可以修改指针,如c=a;

            char a[]="abc";这是定义一个数组,然后把常量区字符串"abc"拷贝到这个数组中来(数组分配所有元素的内存空间)。所

            以操作和常量区的“abc”没有关联,故可以赋值:a[0]='d',OK.但是不能修改a,如a=c错,a就像是const属性的指针。

            a与b,e与f的地址是不同的所以a==b为0,e==f为0.但是c与d,g与h的都是指向同一个常量区的地址,所以相等。

其中,strlen(a)=strlen(c)=3;sizeof(a)=4,sizeof(c)=4;sizeof(c)=4是因为c是指针,指针的sizeof是一个定值为4.

 

const char *str=“abcd”与char *str=“abcd”的区别

1.浅白一点:前者如果修改某个字符(str[1]='x')的时候在编译时就会报错,二后者在运行时报错。两者都不允许这种修改。前者在编译时报错是因为限制符const的作用。后者是因为''abcd'在常量区,str只是指向常量区的地址的指针,没法进行修改。

2.char p[]="1234";

   const char* str="abcd";

   str=p;

   str[2]='1';//非法

   str变成指向数组p的指针,数组名表示地址。但是有const char限制,指针是没法修改数组内容的(数组的内容都在栈区)。

  如果:char* str="abcd";

              str=p;

              str[2]='1';//合法。   数组及其元素在栈区是云寻修改的。

 

char *与char[]的区别:

问题引入:

     char *c="abc" 和char c[]="abc"前者改变其内容程序会崩溃,后者完全正确。

代码:

        #include<iostream> 
  using namespace std;
  main()
  {
  char *c1 = "abc";
  char c2[] = "abc";
  char *c3 = ( char* )malloc(3);
  c3 = "abc";
  printf("%d %d %s\n",&c1,c1,c1);
  printf("%d %d %s\n",&c2,c2,c2);
  printf("%d %d %s\n",&c3,c3,c3);
  getchar();
  }

运行结果

  2293628 4199056 abc   c1存储的是"abc"在常量区的地址,&c1表示指针的地址,此地址存储在栈区

  2293624 2293624 abc   c2本身表示的就是地址,所以与&c2是相同的

  2293620 4199056 abc   &c3表示的指针c3的地址,此地址也是存储在栈区,c3指向的地址存储的内容"abc"在常量区

                                                    已经存在,所以c3存储的也是"abc"在常量区的地址与c1是相同的。

同时我们还可一发现有四个地址是在一个区域的,说明这些都存在与栈区。而''abc''存在于常量区。这两个地址还是有意定距离的。

 

存取效率:

char s1[]="aaaaaaaaaaa";

char *s2="bbbbbbbbbbb";

aaaaaaaaaa是在运行时赋值的。而bbbbbbbbbbb是在编译时就确定的,因为他存在于栈区。但是,在以后的存取过程中,在栈上数组比指针所指向的字符串要快。

 

总结:

char *c1="abc";实际上先是在文字常量区分配一块内存存放"abc",然后在栈上分配一地址给c1并指向这块地址,然后改变常量"abc"自然会崩溃。

char c2[]="abc";实际上abc分配内存地址的地方在栈区与上面的地址是不同的,是可以修改的。


深入思考:

        #include  <iostream>
  using namespace std;
  main()
  {
  char *c1 = "abc";
  char c2[] = "abc";
  char *c3 = ( char* )malloc(3); //分配来的3个字节在堆区
  //  *c3 = "abc" //error ==>报错:不能将const char* 类型的值分配给char 类型的实体,所以必须

                                                                   c3=“abc”,两边都是char*类型
  strcpy(c3,"abc"); ==>把第二个参数含有NULL的字符串赋值到以c3开始的地址空间,并且两个参数所指的内存区域不

                                              可以重叠
  c3[0] = 'g';

        //c3="abc";c3[0]='g'; //error==>报错:c3指向的是在常量区的地址,而不是指向自己分配的地址,所以不能修改
  printf("%d %d %s\n",&c1,c1,c1);
  printf("%d %d %s\n",&c2,c2,c2);
  printf("%d %d %s\n",&c3,c3,c3);
  getchar();
  }

输出:

  2293628 4199056 abc

  2293624 2293624 abc

  2293620 4012976 gbc    可以看到c1存储的地址与c3存储的地址是不同的。

 

实例:

char* get_str(void)
{
    char str[] = {"abcd"};                              
    return str;
}

       char str[] = {"abcd"};定义了一个局部字符数组,尽管是数组,但它是一个局部变量,返回它的地址肯定是一个已经释放了的空间的地址。
       此函数返回的是内部一个局部字符数组str的地址,且函数调用完毕后 此数组被销毁,所以你返回的指针也就指向一块被销毁的内存,这种写法是错误的

char* get_str(void)
{
    char *str = {"abcd"};
    return str;
}

char* str = {"abcd"};表示先定义个字符串常量,并将其地址赋给str。
      此函数返回的是字符串常量的地址,而像这种字符串都是属于全局的,在编译的时候就已经分配了内存了,只有程序退出的时候才会被销毁,所以返回它的地址是没有问题的,但是你最好返回常量指针,因为你不能去改变字符串常量的值。

    这个str就在栈里面,但后面的字符串在常量区,函数返回的时候,先将常量区的地址返回,然后作用域结束,释放str在栈里面的空间。


准确的说,上面两个“abc"都是存储在静态存储区,即常量区,存储在堆上 。常量区是可读不可写的。 所以任何试图对常量区进行写的操作都是非法的,当然了,这也不是一定不可写的,你可以采取某种渠道改变常量区的内存属性,比如改变pe相关节的属性就可以 对常量区进行读写,当然了,这个目前可以忽略。
       那么为什么str[] = "abc";      可以写呢?   答案就在str[] = "abc";会有一个额外的拷贝过程,即把常量区的 "abc"拷贝到栈内存去,所以就可以写了。

 

C风格字符串与string的区别与联系:

C:字符串一般存储在一个字符数组中,通过一个char* 类型的指针来操纵它

       常用的字符串函数:字符串不包含\0的长度:int strlen(const char*)

                                           两字符串是否相等:int strcmp(const char*, const char*)

                                           将第二个字符串拷贝到第一个字符串中:char* strcpy(char*, const char*)

     相关的头文件:#include<cstring>

     操作实例:const char *st=“this is a dog”;系统在内部把字符串常量存储在一个字符串数组中,然后让st指向该数组的第一个元素。操作手段一般是while(*st++){.....};

例如: int string_length(const char* st){

                   int cnt=0;

                   if(st){

                        while(*st++)

                               __cnt;

                   }

                   return cnt;

             }

 

string类型:头文件 #include<string> string st(“this is a dog”)

                      st.size()返回的长度不包括终止空字符

                     用0一个string初始化另一个string对象:string st3(st);

                     比较两个string对象用==:两者相等返回true,否则返回false===>if(str1==str2)

                     拷贝一个字符串用=:str2=str1;

                     连接两个字符串用+:string st3=st2+st1;或者st2+=st1;

混合使用C风格的字符串以及string对象:

                   const char* pc=",";

                   string s1("hello");

                   string s2("world");

                   string s3=s1+pc+s2+"\n";   机理:string类型能够自动将C风格的字符串转换成string对象

可以将C风格的字符串赋值给一个string对象:

                 string s1;

                 const char *pc="this is a dog";

                 s1=pc;

但是反向的string向C风格的字符串的转换不是自动的,必须显式的调用c_str():

               char *str=s1;  //错误

               char *str=s1.c_str();  //几乎正确  字面意思表示:指向字符数组起始处的字符指针

               为了防止字符数组被程序直接处理,c_str()返回了一个指向常量数组的指针

               const char* str=s1.c_str();  //正确

string类型支持下标操作访问单个字符。

              例如:string str("fa.disney.com");

                          int size=str.size();

                          for(int ix=0;ix<size;i++){

                                    if(str[ix]=='.')

                                            str[ix]='_';

                         }

 

 

分享到:
评论

相关推荐

    string和char*

    string 和 char* 的区别和联系 在 C++ 编程中,字符串是一种常用的数据类型,string、CString 和 char*都是字符串的 представители,每种类型都有其特点和使用场景。下面我们将详细介绍 string、...

    std::string、char*、const char*转托管byte数组或托管字符串String

    std::string、char*、const char*转托管byte数组或托管字符串String std::string、char*、const char*是C++中三个不同的字符串表示方式,它们都可以转换为托管的byte数组或字符串String,但是在C++/CLI中,它们的...

    string、cstring 、char* 转化问题

    例如:char *p=string.c_str(); 这里使用了 string 的 c_str() 方法将 string 转换为 const char*,然后将其赋值给 char*。 4. char * 转 string string 可以使用 constructor 将 char* 转换为 string。例如:...

    CString,string,char*之间的转换

    char *p=string.c_str(); 4 char * to string string str(char*); 5 CString to char * strcpy(char,CString,sizeof(char)); 6 char * to CString CString.format("%s",char*); CString的format方法是非常好用的。...

    QString含汉字时,完美转char*和unsigned char*

    此为QString无损转char*和unsigned char* 。 当QString内容包含汉字时,转换char*等会发生失败。此接口解决了该问题。使用后char*与unsigned char*的qDebug()输出与QString输出结果相同。 注意,该函数返回unsigned ...

    VC中CString,int,string,char*之间的转换

    CString、int、string、char* 是四种常用的数据类型,在 VC 中它们之间的转换非常常见,本文将详细介绍它们之间的转换方法以及应用实例。 string 转 CString 使用 CString::Format 函数可以将 string 转换为 ...

    golang调用c++DLL传递char*型参数读取返回char*字符串内容

    golang调用c++DLL返回值为char*参数为const char*,读取返回DLL返回值,传递char*型参数

    C++中string转换为char*类型返回后乱码问题解决

    Serialize1(TreeNode *root) 其函数返回类型为char*,但是我在实现的过程中为了更方便的操作添加字符串使用的是C++中string类型的变量,这就导致我最后得到的结果res是string类型,若是要返回需要转化为char *类型...

    cstring string char*的对比,使用,相互转换的介绍

    ### cstring、string、char* 的对比、使用与相互转换 #### 一、概述 `string` 和 `CString` 均为字符串处理类,分别适用于不同的编程环境和框架。 - **string**: 属于标准模板库 (STL) 定义的字符串类,广泛应用...

    C++类型转换(char* string cstring unicode ansi )转换

    char *p = (LPSTR)(LPCTSTR)cstr; 这段代码将 CString 对象 cstr 转换成 char* 类型的指针 p。 char* 转 CString: char *p; CString cstr; cstr = p; 这段代码将 char* 类型的指针 p 转换成 CString 对象 cstr...

    char*转为LPCWSTR

    综上所述,`char*` 转换为 `LPCWSTR` 主要有三种方法:使用 `MultiByteToWideChar` 函数、直接定义宽字符字符串以及使用 `_T` 宏。每种方法都有其适用场景和优缺点,开发者可以根据具体需求选择合适的方法。

    CString string char * int double float 之间转化大全

    在本文中,我们将详细介绍 CString、string、char* 之间的转化关系,以及它们之间的比较、运算符重载、常用算法等知识点。 一、CString、string、char* 之间的比较 CString、string 和 char* 都是字符串模板类,但...

    C语言合并多个char *类型的字符串

    在C语言中,合并多个`char *`类型的字符串是一项常见的任务,这通常涉及到字符串操作和内存管理。在给定的场景中,`main.c`文件是测试程序,它调用了`tools.h`头文件中定义的`MultiCombine`函数,这个函数的目的是将...

    通过string转换比较好些,很多重载函数要么是char * ,要么是String

    在探讨字符串处理的过程中,我们经常会遇到不同的数据类型之间的转换问题,尤其是在C++中,常见的有`char *`、`std::string`等不同形式的字符串表示。本篇将重点讨论如何利用`std::string`进行数据类型转换,并分析...

    char*指针成员变量的重载

    dd(char*d) { P = new char[256]; strcpy(P, d); } // 拷贝构造函数 dd(dd&d) { P = new char[256]; strcpy(P, d.P); } // 析构函数,释放P指向的内存 ~dd() { delete[] P; P = nullptr; } // 获取P指针...

    VC++ string_format(const char* format, ...)

    能够按照格式化输出字符串数据,长度不受限制,亲测十几兆都正常。 #include &lt;string&gt; using namespace std;

    const char*转LPCWSTR 字符串转换

    std::string str(const_char_ptr); std::wstring wstr(str.begin(), str.end()); LPCWSTR wide_ptr = wstr.c_str(); // 现在,wide_ptr是一个LPCWSTR,可以传递给Windows API ``` 这种方法假设输入的`const ...

    字符串逆序的几种方法字符串逆序的几种方法 1.普通逆序 分配一个与原字符串等长的字符数组; 反向拷贝一下即可 char* r

    char* reverseString(char* s) { //将q指向字符串最后一个字符 char* q = s ; while( *q ) { q++; } q -= 1 ; //分配空间,存储逆序后的字符串。 char* p = (char*)malloc(sizeof(char*)*(q-s+1)); ...

    QString和char以及string之间的赋值详解

    一、QString赋值给char*...二 、char [] 赋值给string  char str[32];  string str2(str);//这样便把str中的值传给了str2 三 、char* 赋值给QString  例如:char *str1;  QString str2;  str2 += str1;//这样便把s

Global site tag (gtag.js) - Google Analytics