精华内容
下载资源
问答
  • 常量字符串例如“abcde”这种的系统会将他们放在常量区,而常量区就是意味着不能修改的,只可以读取的数据区域,并且相同常量字符串只有一份。void string2(){ char* p = "abcde"; printf("%p\n"...

    常量字符串例如“abcde”这种的系统会将他们放在常量区,而常量区就是意味着不能修改的,只可以读取的数据区域,并且相同常量字符串只有一份。

    void string2()
    {
    char* p = "abcde";
    printf("%p\n", p);
    char*p1 = "abcde";
    printf("%p\n", p1);

    }


    如上,p1和p的地址是一样的,他们都指向的是同一个常量向量,这是编译器做的优化。

    char *string1()
    {
    char str[20] = "abcde";
    return str;
    }
    char* string2()
    {
    char* p = "abcde";
    return p;
    }
    void main()
    {
    char * p = string1();
    printf("%s\n", p);
    char *pp = string2();
    printf("%s", pp);
    system("pause");
    }


    上面定义了一个字符数组char str[20] = "abcde";等于字符常量,还定义了一个char* p = "abcde";指针指向字符常量,同时返回他们的首地址,结果却是指针可以正确输出而数组却不可以,这是为什么呢?存的都是常量字符串。这是因为char str[20],系统给它分配了二十个字节连续的地址,然后把这篇内存的首地给受托人,最后用abcde去初始化数组,地址已经存在,内存也已经存在,所以系统会把用来初始化的常量字符串从常量区复制一份然后放入数组的内存区域中。所以数组str的内存区域hi在栈区,而栈区就是用完就会回收,所以函数结束内存被回收了从而导致了错误的结果。同时这也意味着char str[20] = "abcde”中的值是可以修改的str[1]=“t”是可以的。但是指针就是直接指向了常量区,不可以对指针指向的字符串进行修改,p[0]=“r”这种操作是不允许的,常量区是不可以修改的。

    展开全文
  • 常量字符串什么位于静态存储区? char *c="zhaobei"; 书上说: "zhaobei"这个字符串被当作常量而且被放置在此程序的内存静态区。 那一般的int i=1; 1也是常量,为什么1就不被放置在此程序的内存静态区...
    常量字符串为什么位于静态存储区?

    char *c="zhaobei";
    书上说: "zhaobei"这个字符串被当作常量而且被放置在此程序的内存静态区。
    那一般的int i=1;
    1也是常量,为什么1就不被放置在此程序的内存静态区了呢?
    请高手指点!

    所有的字符窜常量都被放在静态内存区
    因为字符串常量很少需要修改,放在静态内存区会提高效率

    例:

    char str1[] = "abc";
    char str2[] = "abc";

    const char str3[] = "abc";
    const char str4[] = "abc";

    const char *str5 = "abc";
    const char *str6 = "abc";

    char *str7 = "abc";
    char *str8 = "abc";


    cout << ( str1 == str2 ) << endl;
    cout << ( str3 == str4 ) << endl;
    cout << ( str5 == str6 ) << endl;
    cout << ( str7 == str8 ) << endl;

    结果是:0 0 1 1
    str1,str2,str3,str4是数组变量,它们有各自的内存空间;
    而str5,str6,str7,str8是指针,它们指向相同的常量区域。

    问题的引入:
    看看下面的程序的输出:

    #include <stdio.h>
    char *returnStr()
    {
     char *p="hello world!";
     return p;
    }
    int main()
    {
     char *str=NULL;//一定要初始化,好习惯
     str=returnStr();
     printf("%s\n", str);
     
     return 0;
    }


    这个没有任何问题,因为"hello world!"是一个字符串常量,存放在静态数据区,
    把该字符串常量存放的静态数据区的首地址赋值给了指针,
    所以returnStr函数退出时,该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

    但是,下面的就有问题:

    #include <stdio.h>
    char *returnStr()
    {
     char p[]="hello world!";
     return p;
    }
    int main()
    {
     char *str=NULL;//一定要初始化,好习惯
     str=returnStr();
     printf("%s\n", str);
     
     return 0;
    }

    "hello world!"是一个字符串常量,存放在静态数据区,没错,
    但是把一个字符串常量赋值给了一个局部变量(char []型数组),该局部变量存放在栈中,
    这样就有两块内容一样的内存,也就是说“char p[]="hello world!";”这条语句让“hello world!”这个字符串在内存中有两份拷贝,一份在动态分配的栈中,另一份在静态存储区。这是与前者最本质的区别,
    当returnStr函数退出时,栈要清空,局部变量的内存也被清空了,
    所以这时的函数返回的是一个已被释放的内存地址,所以打印出来的是乱码。

    如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。如下:

    #include <stdio.h>
    char *returnStr()
    {
     static char p[]="hello world!";
     return p;
    }
    int main()
    {
     char *str=NULL;
     str=returnStr();
     printf("%s\n", str);
     
     return 0;
    }


    这个问题可以通过下面的一个例子来更好的说明:

    #include <stdio.h>
    //返回的是局部变量的地址,该地址位于动态数据区,栈里

    char *s1()
    {
     char* p1 = "qqq";//为了测试‘
    char p[]="Hello world!"’中的字符串在静态存储区是否也有一份拷贝
     char p[]="Hello world!";
     char* p2 = "w";
    //为了测试‘char p[]="Hello world!"’中的字符串在静态存储区是否也有一份拷贝
     printf("in s1 p=%p\n", p);
     printf("in s1 p1=%p\n", p1);
     printf("in s1: string's address: %p\n", &("Hello world!"));
     printf("in s1 p2=%p\n", p2);
     return p;
    }

    //返回的是字符串常量的地址,该地址位于静态数据区

    char *s2()
    {
     char *q="Hello world!";
     printf("in s2 q=%p\n", q);
     printf("in s2: string's address: %p\n", &("Hello world!"));
     return q;
    }

    //返回的是静态局部变量的地址,该地址位于静态数据区

    char *s3()
    {
     static char r[]="Hello world!";
     printf("in s3 r=%p\n", r);
     printf("in s3: string's address: %p\n", &("Hello world!"));
     return r;
    }

    int main()
    {
     char *t1, *t2, *t3;
     t1=s1();
     t2=s2();
     t3=s3();
     
     printf("in main:");
     printf("p=%p, q=%p, r=%p\n", t1, t2, t3);

     printf("%s\n", t1);
     printf("%s\n", t2);
     printf("%s\n", t3);
     
     return 0;
    }

    运行输出结果:

    in s1 p=0013FF0C
    in s1 p1=00431084
    in s1: string's address: 00431074
    in s1 p2=00431070
    in s2 q=00431074
    in s2: string's address: 00431074
    in s3 r=00434DC0
    in s3: string's address: 00431074
    in main:p=0013FF0C, q=00431074, r=00434DC0
    $
    Hello world!
    Hello world!


    这个结果正好应证了上面解释,同时,还可是得出一个结论:
    字符串常量,之所以称之为常量,因为它可一看作是一个没有命名的字符串且为常量,存放在静态数据区。
    这里说的静态数据区,是相对于堆、栈等动态数据区而言的。
    静态数据区存放的是全局变量和静态变量,从这一点上来说,字符串常量又可以称之为一个无名的静态变量,
    因为"Hello world!"这个字符串在函数 s1和s2 中都引用了,但在内存中却只有一份拷贝,这与静态变量性质相当神似。
    展开全文
  • C语言常量字符串

    千次阅读 2017-11-08 19:47:01
    关于C语言字符串常量不可修改,因为...但是实际上是与常量字符串的内存体现有关。bodata段各类段bss段: BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by S

    关于C语言字符串常量不可修改,起初误认为是编译器
    把这样的代码

    char *s=""str";
    

    优化成了
    const char*="str".
    const属性也去不了。

    但是实际上是与常量字符串的内存体现有关。bodata段

    各类段

    bss段:

    BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。BSS段属于静态内存分配。

    data段:

    数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

    text段:

    代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

    rodata段:

    存放C中的字符串和#define定义的常量

    heap堆:

    堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
    stack栈:
    是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

    回答

    以下摘自:https://www.zhihu.com/question/20779337

    C语言目前有两个主要标准C89和C99。这两个标准中对字符串常量的定义类似。要点:

    类型是char[] (原因不明,没有看到过权威解释,估计是历史遗留。)
    连续存储,末尾自动添加\0
    静态存储
    相同值常量的地址可以不同
    修改字符是未定义行为
    

    因为.rodata和.text一样是操作系统保护只读的。这就是标准中所说的未定义行为。实际中大部分操作系统(没有测试过)应该都会按照内存越权访问处理。

    这样做的好处并不明显。理论上fork的时候可以不拷贝.rodata,但主流的fork都实现了Copy-on-write,性能上应该差别不大了。其他的好处也不大。

    简单来说,这样做既没有什么明显的好处,也没有太大的坏处,很可能只是Dennis Ritchie et al拍脑袋的一个决定,原因可能就是没有原因。考虑到C并不是一个精心设计的语言,这种小问题并不少见。例如史上最昂贵的一个字节的错误(The Most Expensive One-byte Mistake)。可惜DR老大已故去,恐怕无从考证了。

    展开全文
  • 初学C/C++,最近经常碰到些与字符串有关的问题,关于字符串的初始化,特别是初始化为一个常量字符串,(本人比较懒,不想去数,也不想用strlen)这才引起了下面这个例子。 记得我第一次是这样写的: char* str=...
    初学C/C++,最近经常碰到些与字符串有关的问题,关于字符串的初始化,特别是初始化为一个常量字符串,(本人比较懒,不想去数,也不想用strlen)这才引起了下面这个例子。
    记得我第一次是这样写的:
        char* str="interesting";
        for(int i=strlen(str);i>0;i--)
            str[i]=st[i-1];
    然后在调试的过程中,str[i]=st[i-1]这条语句出错,因此不得不中断。(本人使用vs2013)...最后,得知常量字符串是存放在常量区的,意思是它是只读的,不能被修改。
    不能修改就不能修改吧,但以我的脾气,那么...换个地方再修理你~~。所以我当时一气之下开始进行malloc。并且还使用的strcpy_s函数(很烦,总是纠结那个源字符串长度+1,实在是不懂这样如何就安全了??)
    代码如下:
            int num = strlen("in ter est ing");
            char* str = (char*)malloc(num + 1);
            strcpy_s(str,num+1, "in ter est ing");
    这样就成功的把常量字符串弄到你的地盘了,无论想干吗你就可以直接上,别多bb。(可读可写)
    

    但其实呢,我发现完全可以使用数组来初始化一个常量字符串;
            char st1[] = "interesting";
            st1[1] = st1[2];
            puts(st1);
    运行也是没有问题,是因为数组是存放在(可能是,取决于你声明的位置)运行时栈里,作为一个变量,它是可以被修改的。
    总结:有两种可以直接修改其值的***简单***的字符串初始化方式,其一是动态内存分配+strcpy复制字符串;其二是用常量字符串来初始化一个数组。均能达到所想要的。   二选一就可以了。
    
    展开全文
  • IDEA 常量字符串过长问题

    千次阅读 2019-07-23 17:57:49
    在编译项目时,出现错误为:“常量字符串过长” ,在网上先找到解决办法。 错误如下: 办法如下: File >> Settings >> Build,Execution,Deployment >> Compiler >>Java Compiler 将 ...
  • 总结关于字符数组、字符串的知识,虽然这些东西都是很基础的内容,但是不少人还是经常会在这些问题上犯错。以下是个人的一些总结,没有什么高端的内容,仅仅希望提醒自己在这些细节上不要再犯错。
  • java: 常量字符串过长

    2020-12-12 00:25:27
    有时超大 json 字符串, 想在代码中声明为字符串变量, 但是运行时, 却编译异常, 提示 java: 常量字符串过长 原因 声明的字符串过长, 超过 65535 个字符 解决 把 json 字符串保存为文件, 然后利用 FileUtils 工具类...
  • Idea报错:Java 常量字符串过长

    万次阅读 2019-09-16 11:35:42
    报错:Error:(77, 27) java: 常量字符串过长 解决方案: 在做一个非常长的json转对象的测试时Intellij IDEA 编译不通过,报”常量字符串太长”,做如下调整即可: 使用 Eclipse编译器 解决问题。 IDEA的操作流程:...
  • 我们知道数组str1和str2是分别开辟了一块内存空间,虽然存储的字符串一致,但地址是不同的,所以第一个应该是str1和str2两者不同 str3和str4是两个相同的常量字符串,它们是不能被更改的,所以它们不可能重复创建,...
  • 常量字符串过长的处理办法

    万次阅读 2018-11-20 19:11:00
    背景:准备分析一个长字符串。一、先把这段文本复制下来,然后赋给变量str String str = 复制的文本;...二、原来常量字符串的长度不能长于65535 - 1字节; 而我的文本长度达到了10W+字节,怎么办呢? Str...
  • 在学习Java过程中,字符串碰到过String和StringBuffer,其中前者是...Swift中,用let 声明的是字符串常量,不能进行修改。用var声明的是字符串变量,可以修改。通过代码来演示。 let str1 = "Hello1" var str2 = "Hello2
  • 1、在日常编程中,可能遇到通过#define将多个常量字符串连接起来,可使用下述方法: #define CompanyID "my company" #define ProductItem "0123456789" #define HardVersion "PCB-101011" #d...
  • java string什么是字符串常量什么是字符串数组,什么是字符串常量池?
  • 最大的区别就是C风格的字符串是静态的,不可以动态变化,使用极为麻烦。 而C++的std::string类型动态管理,非常方便。 C风格字符串和char数组是不一样的,看下面两种定义: char carr1 = {'a', 'b', 'c'}; ...
  • 定义常量字符串

    2016-05-13 08:04:51
  • android studio错误: 常量字符串过长

    千次阅读 2019-01-02 09:04:09
    android studio 错误: 常量字符串过长错误 省市区三级联动,位置字符串。 这样不行 改用json方案 ,读取array中文件 String provsData = new GetJsonDataUtil().getJson(activity, "provsData.json");//...
  • symbian 如何定义常量字符串数组

    千次阅读 2010-09-08 09:08:00
     对于常量字符串可以用_LIT(KTest,"Test") , _LIT8(KTest,"Test"); 前者是16位字符串,即每个字符占字节2位,后都是8位字符串,每字符占字节一位。  定义8位常量字符串数组:  const TPtrC8 g_...
  • 测试的时候遇到这个问题,idea编译不过,String 赋值的常量字符串过长。 String 有没有长度限制呢 1、String的数据结构是 char value[]。数组的长度是int类型,最大值为2的31次方-1= 2147483647(2G),所以String最多...
  • 常量字符串的查找 修改常量字符串 保存修改后的PE文件
  • IntelliJ IDEA Error:(24, 35) java: 常量字符串过长 在转换一个JSON转Java对象是 idea 编译不通过 提示:Error:(24, 35) java: 常量字符串过长 File -> Settings -> Build,Execution,...
  • #include #define NAME "xiao long li "; int main (void) { printf("%s",NAME); } ![图片说明](https://img-ask.csdn.net/upload/201506/19/1434694332_15296.png)
  • @[TOC](idea报错Error:(44, 22) java: 常量字符串过长) idea报错Error:(44, 22) java: 常量字符串过长 找到idea——>Settings——>Build——>Compiler——>java Compiler 将javac改成Eclipse ...
  • 1,需要给变量字符串指针new或者malloc一块空间。 2,使用strcpy,将
  • 什么是字符串常量池?

    千次阅读 多人点赞 2019-06-14 20:43:00
    什么是字符串常量池?面试官Q1:请问什么是字符串常量池?字符串常量池的设计意图是什么?功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的...
  • 1.指针到底能不能修改其指向的常量字符串?今天做一个字符串右移函数时,直接使用指针来修改字符串常量的值出现了奇怪运行时错误。  代码如下: #include"stdio.h" #include"string.h" void ...
  • 在编译项目时,出现错误为:“常量字符串过长” ,我当时想这个问题需要去研究根本。后来就没后来拉。只好在网上先找到解决办法。 办法如下: File &gt;&gt; Settings &gt;&gt; Build,...
  • 如果是字符串字面量(string literals),如“abc"、"1a2b"之类写在代码中的字符串literals,那么允许的最大长度取决于字符串常量池中的存储大小,也就是字符串在class格式文件中的存储格式: CONSTA
  • 常量字符串存储与销毁引发的误解

    千次阅读 2011-03-06 03:04:00
    这边文章主要讨论常量字符串存储与销毁引发的误解,问题出现的本质原因在于编译器对堆、栈和静态存储区的使用策略,以及VS开发环境对Debug版本和Release版本的处理方式不同。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 482,304
精华内容 192,921
关键字:

常量字符串是什么