【问题标题】:Initialization strings in CC中的初始化字符串
【发布时间】:2010-07-20 23:46:58
【问题描述】:

我有一个关于如何操作 c 字符串初始化的正确方法的问题 例如下一个代码,并不总是正确的。

char *something;
something = "zzzzzzzzzzzzzzzzzz";

我测试了一点点增加 zeta 的数量,实际上程序在大约两行内崩溃,那么这个 char 数组的实际大小限制是多少?我怎么能确定它不会崩溃,这个限制实现是否依赖?以下代码是我必须始终使用的正确方法吗?

char something[FIXEDSIZE];
strcpy(something, "zzzzzzzzzzzzzzzzzzz");

【问题讨论】:

  • const char* something = "zzzzzzzzzzzzzz";您指向的是 const 数据。
  • 如果您还没有解决这个问题,请发布完整的代码。正如大多数人所说,这不应该自行崩溃

标签: c arrays initialization char


【解决方案1】:

正如您所说,操纵此字符串会导致未定义的行为:

char *something;
something = "zzzzzzzzzzzzzzzzzz";

如果你想知道为什么,see "C String literals: Where do they go?"

如果你打算完全操纵你的字符串,(即如果你希望它是可变的)你应该使用这个:

char something[] = "skjdghskfjhgfsj";

否则,只需将您的char * 声明为const char * 以表明它指向一个常量。

在第二个例子中,编译器会很聪明地把它声明为堆栈上的一个数组,它的大小正好可以容纳字符串。因此,它的大小受您的堆栈限制。

当然,无论如何您都可能希望指定大小,因为知道何时操作字符串通常很有用。

【讨论】:

  • char something[] = "zzzzzzzzzzzzzzz" 适用于可变字符串,并且更难搞砸。
【解决方案2】:

第二个总是正确的。

只有当你从不改变字符串时第一个才是正确的,因为你已经分配了一个指向固定数据的指针。

【讨论】:

  • 我的错误。 (显然其他人也是 =P)我投了反对票,因为我认为这个答案没有解决 OP 的实际问题(即“这个 char 数组的实际大小限制是多少?”和“下面的代码是正确的方法吗?我总是必须使用?”)。此外,OP 已经声明第一个只是有时是正确的。但我猜他记对了,所以他一定很满意!
【解决方案3】:

第一个例子是不正确的,只是char *something 应该是const char *something。否则,这个:

const char *something = "fooooooooooooooooooooooobar";

...应该可以工作,并且不应该崩溃。

char something[FIXEDSIZE];

...但是,如果您溢出堆栈,这通常会因堆栈溢出而崩溃,这取决于堆栈有多大、该数组有多大、调用它的位置等。

【讨论】:

  • 你能再解释一下,const的原因是什么?
  • @BC,如果声明是自动变量,它可能是一个堆栈。由于 OP 没有提供太多上下文,我们不知道声明是在文件范围内还是在函数内的某个较小范围内。
  • 'const' 通知编译器您承诺不会修改 'something' 指向的内存。如果您进行此更改,您应该会在实际上错误的代码上收到一条警告消息,这就是您现在崩溃的地方。
  • @voodoomsr,const char *"abc"等常量字符串的类型。它表示something 指向的字符是不可变的承诺。它允许在编译时检查由something[3] = 'd'(可能应该是something[3] == 'd')之类的代码引起的错误,因为你不能这样做,因为你说过了。
  • 总之,这两种方式总是正确的。如果我知道我不会修改字符串,我应该使用 const 关键字只是为了编译检查和更好的程序语义,但不是因为是强制性的。我真的好吗?我仍然有一个矛盾......我写了一个程序,使用 scanf("%s",something 请求一个字符串。真正的大字符串崩溃,小字符串工作正常......为什么?
【解决方案4】:

first 不应该崩溃。 second 将在 'z' + 1 的数量超过堆栈页面上的可用空间时崩溃,或者如果您尝试从函数返回。

【讨论】:

  • 如果您通过溢出堆栈以某种方式调用未定义的行为,第二个可能会崩溃,但是“从函数返回”与崩溃不再相关,然后添加两个变量。
  • 如果你将 100 个字符分配给一个 30 个字符的数组,这将是非常相关的。返回地址很可能被溢出的字符串破坏了——这就是缓冲区溢出的工作方式,它们曾经就像闯入服务器等的#1 方式。随机内容导致崩溃;特别畸形的内容可以让您获得根/系统访问权限。
  • 好吧,在我的测试中,第一个因真正的大字符串而崩溃
  • @cHao:啊,你是对的……我总是错误地想象堆栈的东西。尽管如此,这是一个实现,尽管它是一个非常流行的实现。
  • 也就是说,我真的不觉得“将 100 个字符分配给 30 个字符的数组”是这里的问题......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多