【问题标题】:what is the meaning of char *s={'h','e','l','l','o','\0'}; in C and how it is different from char *s="hello";? [duplicate]char *s={'h','e','l','l','o','\0'}是什么意思;在 C 中,它与 char *s="hello"; 有何不同? [复制]
【发布时间】:2015-11-13 08:20:12
【问题描述】:

char *s={'h','e','l','l','o','\0'}; --- 给出警告:

warning: (near initialization for ‘s’)
warning: excess elements in scalar initializer

但是char *s="hello"; 通过在只读内存中为 6 个字符分配内存空间并指向该特定位置来显示 hello。

但是char *s={'h','e','l','l','o','\0'}; 到底是什么?它有何不同?

【问题讨论】:

  • { … } 本身不是一个数组,它是一个花括号初始化列表。 char *s = { 'h', 'e', … } 正在尝试使用字符 'h' 初始化指针并丢弃其余字符。 (但所有这些都可以仅从错误消息中推断出来。)

标签: c


【解决方案1】:

像"hello" 这样的字符串文字被视为指向字符的指针或字符数组,具体取决于您的使用方式。

char *s = "hello";    // treats the string literal as pointer-to-char
char s[] = "hello";   // treats the string literal as array-of-char

像{'h','e','l','l','o','\0'} 这样的初始化器被视为一个数组。它不能分配给指针。

char *s = {'h','e','l','l','o','\0'};   // this is NOT valid
char s[] = {'h','e','l','l','o','\0'};  // same as char s[] = "hello"

【讨论】:

  • treats the string literal as pointer-to-char - 不,它不是,字符串文字始终是char 的数组。只是数组通常会衰减成指针,用数组初始化指针也不例外。
  • 从语言律师的角度来看,您是正确的。但有时律师说话会混淆而不是阐明。在我看来,说“它是一个衰减为指针的数组” 与说它是“被视为指针” 是一样的。我所做的只是跳过中间步骤,直奔主题。
【解决方案2】:

区别在于"hello" 是一个字符串文字,{'h', 'e', 'l', 'l', 'o', '\0'} 是一个初始化列表。将char* 分配给字符串字面量的含义是让指针指向字符串,而将char* 分配给初始化列表的含义是将其分配给第一个值(即'h'转换为char*)。

使用初始化列表的正确方法是改用char 数组:

char s[] = {'h', 'e', 'l', 'l', 'o', '\0'};

但这里仍然存在差异,因为这样你最终应该得到一个可变缓冲区。这里初始化器列表用作值列表来初始化数组中的元素。这是一个快捷方式:

char s[6];

s[0] = 'h';
s[1] = 'e';
s[2] = 'l';
s[3] = 'l';
s[4] = 'o';
s[5] = '\0';

【讨论】:

  • “...的含义只是将其分配给第一个值” - 在标准 C 中它是格式错误的。指针最多可以有一个初始化器。您描述的行为是 GCC 扩展。
  • 另外一个 gcc 扩展是 'h' 被视为 (char *)'h'
  • @M.M 你的第二条评论我想说的是不正确的。这两种情况似乎也被 MSVC 接受(因此,如果它们是扩展,它们不是非常特定于 GCC)。
【解决方案3】:
#include <stdio.h>

int main (void) {

    char *s1 = "hello";                  /* creates a string literal   */
    char s2[] = {'h','e','l','l','o',0}; /* creates a character array  */

    printf ("\n s1 : %s\n s2 : %s\n\n", s1, s2);

    return 0;
}

输出

$ ./bin/s1s2

 s1 : hello
 s2 : hello

字符数组 's2' 和字符串字面量 's1' 的主要区别在于字符串字面量 是创建后不能再创建的被改变。字符数组可以用作任何其他数组或以 null 结尾的字符串。

【讨论】:

  • 不能保证将字符串文字放在只读内存中;事实上,即使存在任何类型的“只读存储器”,也不是该语言所关心的。
  • 我正在从文件转储到汇编和“你好”在 .rodata 部分中愉快地交谈。
  • @DavidCRankin 在问题或您的答案中都没有组装。这是一个 C 语言问题,它是关于与汇编无关的抽象语言结构;因此,您应该从 C 语言的角度而不是从汇编的角度来回答它。渗透无用的实现细节不会增加任何价值,只会造成混乱,不会清除它。
  • 不值得为语义而战。
  • 在 C 语言中,覆盖字符串文字将是“未定义的行为”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-17
  • 2016-06-20
  • 2011-01-28
  • 2015-03-06
  • 2010-12-14
相关资源
最近更新 更多