【问题标题】:What is the difference between these two strings? [duplicate]这两个字符串有什么区别? [复制]
【发布时间】:2013-05-19 15:51:38
【问题描述】:

第 1 部分

我有 2 个字符串,它们的定义方式如下-

char s1[] = "foo";
char *s2 = "foo";

当我尝试更改这些字符串的一个字符时,比如第二个字符 -

char s1[1] = 'x';
char s2[1] = 'x';

字符串s1 中的字符发生了变化,但是更改字符串s2 中的字符给了我这个错误-Segmentation fault (core dumped)

为什么会这样?

为什么我无法更改以其他方式定义的字符串的字符?


第 2 部分

字符串(它们是字符数组,对吗?)可以使用 -char *s = "foo" 进行初始化 但是为什么当我尝试使用 int *arr = {1, 2, 3} 之类的相同内容初始化不同类型的数组时,编译器会发出警告?

foo.c: In function ‘main’:
foo.c:5:5: warning: initialization makes pointer from integer without a cast [enabled by default]
foo.c:5:5: warning: (near initialization for ‘foo’) [enabled by default]
foo.c:5:5: warning: excess elements in scalar initializer [enabled by default]
foo.c:5:5: warning: (near initialization for ‘foo’) [enabled by default]
foo.c:5:5: warning: excess elements in scalar initializer [enabled by default]
foo.c:5:5: warning: (near initialization for ‘foo’) [enabled by default]

注意:我的编译器是 GCC。

【问题讨论】:

  • s1 是一个数组(有 4 个元素); s2 是一个指针(指向具有 4 个元素的(不可修改的)数组的第一个元素)。 “字符串”是一个数组,其中一个元素是'\0'。阅读comp.lang.c FAQ,从第 6 节开始。
  • @KingsIndian 还有一个PART 2
  • @pmg 它不必是“不可修改的”。只有修改它是UB。有细微的差别。
  • @KingsIndian:我的意思是“在 UB 的惩罚下不可修改”。关键是,与某些人的看法不同,在 C 中,字符串文字不是常量:它的类型是 char [N] /* with N large enough for all elements and the nul byte */,而不是 const char[N]。请注意,出于这个原因,我没有说“const”(或“constant”):)

标签: c++ c arrays pointers gcc


【解决方案1】:

第一个是一个字符串,它是一个字符数组,用字符串“foo”中的字符填充,第二个是指向一个值为“foo”的常量的指针。由于第二个是常量,因此不允许对其进行修改。

不,您不能初始化指向一组值的指针 - 因为指针没有实际内存来存储分配给它的值。你需要让它指向另一个数组:

int foox[3] = { 1, 2, 3 };
int *foo = foox;

或者你需要分配一些内存,然后存储值:

int *foo = malloc(sizeof(int) * 3);

foo[0] = 1; 
foo[1] = 2; 
foo[2] = 3; 

【讨论】:

  • 那么我可以称这样的字符串是不可变的吗?
  • 该标准说写入它们是“未定义的行为” - 在某些情况下您完全有可能写入这样的字符串 [例如使用 Turbo C++,你可能可以,因为它为 DOS 生成代码,它没有任何写保护内存的能力,所以没有什么可以阻止你写入字符串 - 或者覆盖你当前正在执行的代码,应该您编写的代码会有意或无意地这样做]。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 2016-05-08
  • 2019-11-15
  • 2012-03-21
  • 2011-01-14
  • 2013-12-17
相关资源
最近更新 更多