3

我发现了很多关于 C#、java 中数据类型可变性的信息……但是纯 C 呢?

例如,int默认情况下在 C 中是不可变的吗?

例如,查看以下代码示例:

#include <stdio.h>

int main()
{
  int a,b,c;
  b=0;
  c=0;
  a=b+c;
  b=1;
  c=2;

  printf("1st time %d\n",a);//gives out 0
  c=3;
  printf("2nd time %d",a);//gives out 0
  return 0;
}

上面的代码表明普通int是不可变的,对吗?

4

4 回答 4

5

[I]s int mutable in C?

简短的回答:是的!

如果你问是否可以改变 C 中的任何内存位置,答案是肯定的。(有时会带来危险的后果!)虽然可以设计一个无法通过您为其创建的 API 直接改变的数据结构,但您几乎可以覆盖纯 C 中的任何内存位置。

难怪有人喜欢,有人不喜欢。

编辑

参考上面罗杰的评论:

#include<stdio.h>

int main (int argc, char *argv[]) {
    const int n = 1;
    int *m = &n;
    *m = 10;
    printf ("%d\n", n); /* prints 10 */
    return 0;
}

所以,是的,可以覆盖 even const ints 的内存位置。

于 2013-05-31T05:00:54.900 回答
4

普通int是可变的。一个实体(不仅声称在某个时候是,而且“确实是”)const在理论上是不可变的,如果硬件和软件合作,通常也是实际上不可变的。

使用限定符定义变量const使其“真正”为 const:

const int c3 = 3;
void f(void) {
    const int c4 = 4;
    ...
}

使用“棘手”的代码(抛弃 const-ness),您可以说服系统将新值写入或尝试写入c3和/或c4

void f(void) {
    const int c4 = 4;
    int *p;

    p = (int *)&c3;
    *p = 99;
    printf("c3 is now %d\n", c3);
}

如果您打电话给f()您,在某些系统上,您可能会发现 c3 更改并变为 99。在其他系统上,您可能会收到“分段错误”或其他运行时错误。

将引用更改为使用c4,同样的事情也会发生——尽管在实践中,很少有系统会产生运行时错误。但是,您可能会完全观察到其他事情:c4 is now 99您可能会得到c4 is now 4.

最后一种情况可能会发生,因为允许编译器假设,在将c4a设为const int4 后,您(程序员)从未更改过它。那*p = 99一定没有改变它(即使它改变了),所以printf可以用另一个只打印 4 的调用来替换对的调用。

对 的引用通常也是如此c3:编译器可以假设由于您承诺永远不会更改它,因此您实际上从未更改过它。这可能会产生令人惊讶的结果,例如:p == &c3为真、c3为 3 和*p为 99。但很可能会出现运行时错误,因为大多数现代编译器和操作系统都会合作c3进入只读区域。

当字符串文字产生数组时(大多数情况下),C 有一个怪癖。这些数组不是const- 限定的,但组成数组的字符无论如何都是只读的(至少在原则上,与 一样const int c3 = 3;)。就像c3,大多数现代系统都设法使它们“真正只读”。

(字符串文字在用作类型对象的初始值设定项时不会生成数组array of char。比较:

char *ronly = "this string is read only";
char rwarray[] = "this string is read/write";

ronly是一个指针,而不是数组,因此字符串字面量生成一个数组并ronly指向该数组的第一个字符。底层数组只读的,即使它的类型是char [25]. Butrwarray是一个数组,而不是一个指针,所以字符串字面量填充它——并将它的大小设置为 26——它是可变的。您必须编写const char roarray[] = ...以使其不可变。[有些人喜欢拼写 type char const [], const 跟在 data-type 之后。这些意思是一样的。])

于 2013-05-31T05:56:52.370 回答
3

我认为您从根本上误解了可变性的含义,或者至少误解了程序语言的工作方式。这是您的代码,其中注释了 a、b 和 c 的值:

#include <stdio.h>

int main(void) // Good practice to declare main with `(void)` instead of ()
{
  int a,b,c;                 // a,b, and c are garbage values (whatever was left in memory)
  b=0;                       // a == garbage, b == 0, c == garbage
  c=0;                       // a == garbage, b == 0, c == 0
  a=b+c;                     // a == 0, b == 0, c == 0
  b=1;                       // a == 0, b == 1, c == 0
  c=2;                       // a == 0, b == 1, c == 2

  printf("1st time %d\n",a);
  c=3;                       // a == 0, b == 0, c == 3 
  printf("2nd time %d",a);
  return 0;
}

一旦a被分配,它就不会因为cb变化而神奇地更新。这与可变性与不变性无关。实际上,通过将 b 和 c 分配给 0,然后再将它们分别重新分配给 1 和 2,您证明了ints(以及 C 中未实际声明的所有数据类型const)实际上是可变的。

于 2015-11-22T19:35:55.090 回答
0

虽然这不是一个答案,但我没有足够的“声誉”来发表评论或投票。

  1. 上面@torek 关于C constness 的精彩文章(也是那些在线测试人员在他们的多项选择题中不包括这些原始问题的原因)。

  2. 作为 javascript 的初学者,术语“可变”意味着(我认为)您可以向它添加属性(使用 javascript 中的“原型”对象)。

无论如何,在您在问题中编写的代码段中,语句 a=b+c; 仅将'a' 的值更改为代码块中该点处的 'b' 和 'c' 的(均为 0),所有 3 个变量都保留其原始地址。因此,您在语句之后对分配变量所做的任何更改都不会影响“a”的值。而在 C 语言中,这一事实并不能使它成为“不可变的”,这意味着值不能改变。

于 2015-01-29T08:28:21.423 回答