const char myStr [] =" hello"之间的区别是什么?和const char * myStr ="你好"

时间:2015-10-12 02:34:13

标签: c++ string pointers arduino

更新:
我认为这个问题与标记为可能重复的问题截然不同,因为我使用了关键字" const。"标记为重复的答案没有充分解释const在这些情况下的含义。在我看来,const应该强制编译器将这两种情况视为相同,即使没有const它们也是不同的。有关详细信息,请参阅我的问题。

const char myStr[] = "hello"const char* myStr = "hello"之间的区别是什么?

当我编译前者时,编译的程序大小比后者多20个字节更多,尽管这两种情况对全局变量占用相同的空间量。编译器优化设置为" -Os"。

更新:
- 就编译的程序大小而言,static const char myStr[] = "hello"const char* myStr = "hello"相同,这与删除变量并将字符串文字"hello"直接传递给函数相同参数。 const char myStr[] = "hello"比刚刚提到的其他案例多20个字节。 char myStr[] = "hello"的程序大小与" const"相同。对应物。

我将此字符串传递给我编写的函数,该函数需要const char str[]作为输入参数。

第2部分:是否需要const char str[]作为输入参数的函数与需要const char* str作为输入参数的参数相同?

相关(但不完全相同)的问题

8 个答案:

答案 0 :(得分:3)

const char myStr[] = "hello";

您定义了一个const char数组,其中包含6个元素(包括' \ 0'),即{'h', 'e', 'l', 'l', 'o'. '\0'},它是从c风格的字符串文字" hello& #34;

const char* myStr = "hello";  

你定义了一个类型const char*的指针,指向c风格的字符串文字"你好"。

您可以在ideone.com上使用sizeofLIVE查看差异,结果显示前者的大小为6,后者的大小为4。 / p>

  

是需要const char str []作为输入参数的函数,该参数与需要const char * str作为输入参数的参数相同吗?

作为函数参数,它们相同,因为当您将函数传递给函数时,数组会衰减到指针。但是使用const char str[]可以更清楚地表明函数期望一个数组,而不仅仅是一个指针(指向单个对象等)。请注意,如果您通过引用传递数组(即const char(&)[size]),它将不会被衰减为指针,并且将保留数组的大小。

答案 1 :(得分:3)

实际上很简单。

const char myStr[] = "Hello, world!\n";

在这种情况下,sizeof(myStr) == 14,因为整个字符串位于堆栈中!它实际上与......相同。

const char myStr[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', '\0' };

现在,像......

char myStr[] = "Hello, world!\n";

非常好,并允许您稍后修改数组的内容。

现在,这......

const char *myStr = "Hello, world!\n";

将为常量字符数组保留内存,即"Hello, world!\n"某处,通常在只读内存中,并将该数组的地址分配给myStr。因此,sizeof(myStr) == sizeof(const char*)

现在,这是一个棘手的问题......

char *myStr = "Hello, world!\n";

在(长)一段时间内,C语言中曾经没有const个关键字。因此,程序员记得可以修改什么,什么不可以修改。在这个例子中,根据类型系统,myStr指向的内存是可修改的,但根据字符串文字的规则,它不是可修改的。因此,修改*myStr涉及未定义的行为。

现在,还有一个额外的细节。根据数组到指针降级的规则,声明类型const char*的参数与声明类型const char[]的参数相同。

答案 2 :(得分:1)

const char* myStr = "hello";  

定义一个字符串常量,其值为" hello"。

char* myStr = "hello";  

定义一个(只读)常量,即使没有const,更改它是未定义的行为。一些编译器(在某些配置中)会因为缺少const而发出警告。

const char myStr[] = "hello";  

定义一个字符串常量,其值为" hello",与上面相同。

char myStr[] = "hello";  

定义了一个可以在以后更改的数组,初始值为" hello"
(数组大小= hello的长度+终止0)

是的,*变体总是不变的,这是件令人讨厌的事情。

制作函数参数时,const char str[]const char *str是相同的。区别仅在于定义新变量时,而不是在指定参数类型等时。

答案 3 :(得分:1)

const char myStr[] = "hello"将字符串复制到缓冲区中。如果它是一个局部变量,它每次都会被压入堆栈,这可能效率较低,除非你把它变为静态,但是你也可以使用const char* myStr = "hello"。您可以将其传递给const char str[]参数。

某些编译器对字符串文字执行字符串池优化。如果您明确要求将其存储在缓冲区中,我怀疑编译器可能不会对缓冲区使用字符串池优化。

因此我推荐const char* myStr = "hello"或更好const char* const myStr = "hello"(因为它可能允许编译器优化内存中的指针变量,因为它知道它不能被更改)。

答案 4 :(得分:1)

在第一种情况下,变量是一个数组,它使用6个字节并且初始化为字符串。如果变量是本地变量,则在使用字符串的内容进入函数时将分配空间。

在第二种情况下,变量是指向数组的指针,而数组则位于其他位置。如果您定义了两个这样的指针,它们可能指向同一位置。如果变量是本地的,则在进入函数时指针会被初始化以指向字符串。如果您愿意,可以稍后为指针指定不同的值,并使其指向其他位置。

我建议你看一下反汇编。虽然编译器可以随意对其进行优化。

传递给函数时,它不会产生任何差异。

答案 5 :(得分:0)

另一个区别:您可以将(const)char * myStr重新分配给不同的char *(或甚至0),但是您不能重新分配(const)char myStr [] - 这将生成编译器错误

答案 6 :(得分:0)

两者看起来与外界相似,但实际上它们的实施方式却截然不同。在这种情况下,我认为关于一张价值1000字的图片的旧线是非常准确的,所以让我们从一对图片开始:

enter image description here

第一个代表char const *myStr = "hello";之类的东西。我们有一个本地指针名myStr,它指向一些包含字符串hello的常量数据。虚线表示这里发生的事情不是数据移动 - myStr只指向字符串文字本身。

第二个代表char const mystr[] = "hello";之类的东西。这仍然有常量数据中字符串的副本。在(例如)进入定义myStr的函数时,该常量数据用于初始化为myStr本身分配的本地存储。在这种情况下,实线表示确实存在数据移动 - 至少在理论上,每次输入包含myStr的函数(假设它在函数内定义)时,相同的数据被复制到新的分配了局部变量。

当然,在您已经显示myStr const数组的情况下,编译器可以实际优化代码以便复制每次进入例行程序时都不会发生。尽管如此,它必须像数组,而不是指针。

例如,在第一种情况下(char const *myStr = ...;),如果您使用sizeof(myStr),则结果必须与sizeof(char const *)相同(通常为4或8)。在第二种情况下(无论任何优化)sizeof(myStr)必须给出数组本身的大小,因此hello将给出六(大小包括终止NUL)。如果你使用了不同的字符串(例如,“你好,你今天怎么样?”)第一种情况不会受到影响 - 你仍然可以获得指针的大小。第二种情况会完全改变 - myStr 字符数组本身,因此更改其包含的字符数将改变其大小(在这种情况下为32,如果我已经算得正确了。)

const而言,它并没有太大改变。在指向文字(char const *myStr = "hello";)的指针的情况下,您不再(从C ++ 11开始)允许创建没有const限定符的指针。在此之前,您可以创建一个非const指针,但您仍然必须基本上行动,就像它是const一样 - 任何通过该指针进行修改的尝试(或任何其他指向字符串文字的指针都会导致未定义的行为。

使用数组(char myStr[] = "...";),const会阻止您修改数组的内容。如上所述,编译器可能理论上能够优化事物,因此它不会在包含函数的每个条目上真正创建本地,并从常量存储初始化该本地。实际上,它几乎是无关紧要的,甚至很难确定(这是大多数原因可以让它开始)。

答案 7 :(得分:0)

在我看来:    static const char myStr [] =" hello&#34 ;;    存储数组' myStr'数据段中的{sizeof(myStr)= strlen(" hello")+ 1},这意味着这是一个运行时事物。它也编译了#34;你好"程序代码段(文本)中的单词。    static const char * myStr =" hello&#34 ;;    只存储一个指针' myStr'数据段中的{sizeof(myStr)=}。和#34;你好"在该计划的代码段。

当您尝试在函数堆栈中使用这两个时:    const char myStr [] ="你好&#34 ;;    意味着您从函数堆栈中显式分配sizeof(myStr)内存,然后执行字符串复制操作,并且字符串复制事项很昂贵。    const char * myStr ="你好&#34 ;;    只需分配一个指针,然后为其分配正确的地址。