Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的字符串常量和数组_C_Arrays_String - Fatal编程技术网

C语言中的字符串常量和数组

C语言中的字符串常量和数组,c,arrays,string,C,Arrays,String,在C语言中,我们可以创建一个指向常量字符串的指针,如 char *s = "abc"; 但既然字符串基本上都是以null结尾的字符数组,为什么不允许这样做呢 char *s = {'a', 'b', 'c' , '\0' }; 您可以编写以下代码: char s[] = { 'a', 'b', 'c', '\0` }; 这和 char s[] = "abc"; 但是,字符串文字实际上是只读的(因为在文本段中)。因此,您应该将字符串文字理解为const char s[](即使它不完全是

在C语言中,我们可以创建一个指向常量字符串的指针,如

char *s = "abc";
但既然字符串基本上都是以null结尾的字符数组,为什么不允许这样做呢

char *s = {'a', 'b', 'c' , '\0' };
您可以编写以下代码:

 char s[] = { 'a', 'b', 'c', '\0` };
这和

 char s[] = "abc";
但是,字符串文字实际上是只读的(因为在文本段中)。因此,您应该将字符串文字理解为
const char s[]
(即使它不完全是这样,如果您非常关心C标准的话)。特别是编码
“abc”[1]=“X”
是(在Linux上可能会因分段冲突而崩溃)

如果您启用所有警告,例如使用
GCC-Wall

当然,C语言中的指针和数组是不同的(数组可以衰减为指针),正如所解释的那样。

您可以编写以下代码:

 char s[] = { 'a', 'b', 'c', '\0` };
这和

 char s[] = "abc";
但是,字符串文字实际上是只读的(因为在文本段中)。因此,您应该将字符串文字理解为
const char s[]
(即使它不完全是这样,如果您非常关心C标准的话)。特别是编码
“abc”[1]=“X”
是(在Linux上可能会因分段冲突而崩溃)

如果您启用所有警告,例如使用
GCC-Wall


当然,C语言中的指针和数组是不同的(数组可以衰减为指针),正如所解释的。

这是因为指针不是数组。(可以将数组衰减为指向第一个元素地址的指针,但指针不能成为数组。)

您可以这样做:

   char s[] = {'a', 'b', 'c', '\0'};
// ^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^
// array      valid initializer for char[]
但不是这个:

   char* s = {'a', 'b', 'c', '\0'};
// ^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^
// pointer   invalid initializer for char*

这是因为指针不是数组。(可以将数组衰减为指向第一个元素地址的指针,但这不会使指针成为数组。)

您可以这样做:

   char s[] = {'a', 'b', 'c', '\0'};
// ^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^
// array      valid initializer for char[]
但不是这个:

   char* s = {'a', 'b', 'c', '\0'};
// ^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^
// pointer   invalid initializer for char*

这基本上是因为语言不允许这样做

字符串文字是类型为
char[N+1]
的表达式,其中
N
是文字的长度。它是指具有静态存储持续时间的匿名数组对象,这意味着该对象在整个程序执行过程中都存在

(注意,与C++不同,它不是<代码> const char [n+1] ,但是试图修改它有未定义的行为。< /P> 和任何数组类型的表达式一样,在大多数上下文中,它隐式转换为指向数组第一个元素的指针

因此,在本宣言中:

char *s = "abc";
表达式
“abc”
隐式转换为指向 数组,用于初始化
s
。但这样写更安全:

const char *s = "abc";
这样您就不会意外地试图修改数组

那么为什么这不起作用呢

char *s = { 'a', 'b', 'c', '\0' };
这是因为
{'a','b','c','0'}
不是一个表达式。它是一个初始值设定项,可用于初始化数组对象,但不能用于初始化指针对象。如果你改写:

char arr[] = { 'a', 'b', 'c', '\0' };
然后使用初始化器初始化数组对象;它不创建数组对象。要使
char*s
版本正常工作,它必须为指针
s
创建一个对象。括号内的初始值设定项列表不能这样做

C99增加了一个新特性,复合文字,在某些方面类似于字符串文字,但更通用。例如,这:

(char[]){ 'a', 'b', 'c', '\0' }
是一个类型为
char[4]
的表达式,同样,与任何数组类型的表达式一样,它在大多数上下文中隐式转换为指针。因此:

char *arr = (char[]){ 'a', 'b', 'c', '\0' };
有效,并使
arr
指向由复合文字创建的匿名数组对象的第一个元素

有一个显著的区别:数组对象的生存期不一定是静态的。如果一个复合文字出现在任何函数之外,那么数组对象在整个程序执行过程中确实存在;否则,它就像一个具有自动存储持续时间的本地对象

如果您使用的编译器不支持C99(*cough*Microsoft*cough*),则始终可以先声明数组对象:

const char arr[] = { 'a', 'b', 'c', '\0' };
const char *s = arr;

另请参见的第6节,该节讨论了数组和指针(并且在消除一些关于它们的常见误解方面做得很好)。

这基本上是因为该语言不允许这样做

字符串文字是类型为
char[N+1]
的表达式,其中
N
是文字的长度。它是指具有静态存储持续时间的匿名数组对象,这意味着该对象在整个程序执行过程中都存在

(注意,与C++不同,它不是<代码> const char [n+1] ,但是试图修改它有未定义的行为。< /P> 和任何数组类型的表达式一样,在大多数上下文中,它隐式转换为指向数组第一个元素的指针

因此,在本宣言中:

char *s = "abc";
表达式
“abc”
隐式转换为指向 数组,用于初始化
s
。但这样写更安全:

const char *s = "abc";
这样您就不会意外地试图修改数组

那么为什么这不起作用呢

char *s = { 'a', 'b', 'c', '\0' };
这是因为
{'a','b','c','0'}
不是一个表达式。它是一个初始值设定项,可用于初始化数组对象,但不能用于初始化指针对象。如果你改写:

char arr[] = { 'a', 'b', 'c', '\0' };
然后使用初始化器初始化数组对象;它不创建数组对象。要使
char*s
版本正常工作,它必须为指针
s
创建一个对象。括号内的初始值设定项列表不能这样做

C99增加了一个新特性,复合文字,在某些方面类似于字符串文字,但更通用。例如,这:<