字符数组是C中表示字符串常量的另一种方式吗?
我们可以说上面的HELLO是一个字符串常量吗?我对此有疑问,因为我们可以更改字符串元素,比如字符数组是C中表示字符串常量的另一种方式吗?,c,arrays,string,C,Arrays,String,我们可以说上面的HELLO是一个字符串常量吗?我对此有疑问,因为我们可以更改字符串元素,比如a[0]='a'。那么,我们是否仍然可以在这里将“HELLO”声明为字符串常量,仅仅因为它的末尾包含一个NULL。字符串是以null结尾的字符数组。字符串常量必须是不可变的。当字符串出现在双引号定义的代码中时(例如,“hello”),它被视为字符串文字。内存中的实际字符数组将是一个字符串。不,这不是C中的字符串常量。顺便说一下,C语言中的任何字符串都必须以“\0”结尾,例如: char a[ ]= "HE
a[0]='a'
。那么,我们是否仍然可以在这里将“HELLO”声明为字符串常量,仅仅因为它的末尾包含一个NULL
。字符串是以null结尾的字符数组。字符串常量必须是不可变的。当字符串出现在双引号定义的代码中时(例如,“hello”
),它被视为字符串文字。内存中的实际字符数组将是一个字符串。不,这不是C中的字符串常量。顺便说一下,C语言中的任何字符串都必须以“\0”结尾,例如:
char a[ ]= "HELLO";
如果要在C代码中添加字符串常量,以下是一个示例:
// '\0' explicitly included as the last element
char str[] = "HELLO";
// '\0' has to be the last element in this case
char str2[] = {'H', 'E', 'L', 'L', 'O', '\0'};
常量字符串的另一个示例:
const const_str[] = "HELLO";
没有
常量是在程序执行过程中不会改变(或不应该改变)的变量。只要你能做a[1]=“d”它不是一个常数
要在c中定义常量字符串,可以采用三种方法:
#define CONST_STR "HELLO"
其他定义不会创建常量字符串,而是可变字符数组,这是另一回事。是的,“HELLO”
仍然是字符串常量(更具体地说,它是字符串文字)
但是,数组a
,其内容被初始化为该常量的副本,而不是。“HELLO”
是一个字符串文字-它被存储为字符的数组,在程序的生命周期内可用。它可能存储在只读内存段中,具体取决于实现(在我的系统上是)。试图修改字符串文字的内容会导致未定义的行为
a
不是字符串文字-它是用字符串文字的内容初始化的char
数组“HELLO”
。您可以根据自己的意愿更改a
的内容(尽管不能存储长度超过5个字符的字符串)
下面是一个简短的程序,用于显示字符串literal“HELLO”
和数组a
之间的关系(以及为便于测量而抛出的指针):
字符串文本“HELLO”
存储为ASCII(或UTF8)字符序列,从地址0x400b30
开始
数组a
从地址0x7fff89062330
开始存储-如您所见,它包含字符串“HELLO”
的副本
指针p
从地址0x7fff89062328
开始存储-它存储字符串文本的地址“HELLO”
(x86是小尾端,因此多字节值从最低有效字节开始存储-您需要从右到左、从下到上读取)
您注意到的一点是“HELLO”
与变量a
和p
之间的地址差异。在我的系统中,“HELLO”
存储在.rodata
内存段中:
Item Address 00 01 02 03
---- ------- -- -- -- --
"HELLO" 0x400b30 48 45 4c 4c HELL
0x400b34 4f 00 22 48 O."H
a 0x7fff89062330 48 45 4c 4c HELL
0x7fff89062334 4f 00 00 00 O...
p 0x7fff89062328 30 0b 40 00 0.@.
0x7fff8906232c 00 00 00 00 ....
$objdump-j.rodata-d strings2
strings2:文件格式elf64-x86-64
节段的拆卸。rodata:
0000000000 400B2C:
400b2c:01 00 02 00 48 45 4c 4f 0022 48 45 4c 4f…您好。“您好”
400b3c:2200610070004164726573004974“。
...
a
和p
从运行时堆栈分配,运行时堆栈从高地址开始,向下向低地址增长 “HELLO”是一个字符串常量a
是从字符串常量初始化的char
s数组。C或C++?在C++ <代码>“text”<代码>中称为字符串literal@NathanOliver:C99§6.4.5也将其称为字符串文字。@BoundaryPositionCool。谢谢不确定C是否调用了相同的东西。或者const char*str=“test”代码>。将宏引入其中只是混淆了问题。const char*WHATEVER=“HELLO”
是最简单、最安全和最快的(总的来说)。@BoundaryPosition仍然使其静态
限制了文件的范围,因此有时它比普通的常量
变量更安全。对于宏,是的,声明一个const
值比声明一个宏更安全,因为它们是在预处理器中处理的,并且不是类型安全的。我想指出的主要区别是*
与[]
,因为您生成了一个不需要的副本。@BoundaryPosition我的错,没有看到*
#include <stdio.h>
#include "dumper.h"
int main( void )
{
char a[] = "HELLO";
char *p = "HELLO";
char *names[] = { "\"HELLO\"", "a", "p" };
void *addrs[] = { "HELLO", a, &p };
size_t sizes[] = { sizeof "HELLO", sizeof a, sizeof p };
dumper( names, addrs, sizes, 3, stdout );
return 0;
}
Item Address 00 01 02 03
---- ------- -- -- -- --
"HELLO" 0x400b30 48 45 4c 4c HELL
0x400b34 4f 00 22 48 O."H
a 0x7fff89062330 48 45 4c 4c HELL
0x7fff89062334 4f 00 00 00 O...
p 0x7fff89062328 30 0b 40 00 0.@.
0x7fff8906232c 00 00 00 00 ....
$ objdump -j .rodata -d strings2
strings2: file format elf64-x86-64
Disassembly of section .rodata:
0000000000400b2c :
400b2c: 01 00 02 00 48 45 4c 4c 4f 00 22 48 45 4c 4c 4f ....HELLO."HELLO
400b3c: 22 00 61 00 70 00 41 64 64 72 65 73 73 00 49 74 ".
...