默认情况下,C中的基本数据类型是可变的还是不可变的?

时间:2013-05-31 04:50:28

标签: c variables types

我在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 个答案:

答案 0 :(得分:5)

[I]s int mutable in C?

答案简短:是的!

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

难怪有人喜欢它,有些则不喜欢。

修改

参考Roger上面的评论:

#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;
}

所以,是的,可以覆盖偶数const int的内存位置。

答案 1 :(得分:4)

普通int是可变的。一个实体(不只是声称在某个时刻,但“真的是”)const在理论上是不可变的,如果硬件和软件合作,通常不是 - 事实上可变的好。

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

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

使用“棘手”代码(抛弃常量),您可以说服系统在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

最后这种情况可能发生,因为允许编译器假设,使c4const int值为4,程序员从未更改过它。 *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]。但rwarray是一个数组,而不是一个指针,因此字符串文字将其填入并将其大小设置为26,并且它是可变的。您必须编写const char roarray[] = ...才能使其不可变。 [有些人喜欢拼写类型char const [],其中const位于数据类型之后。这些意思相同。])

答案 2 :(得分: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,您证明了int s(以及C中未实际声明为const的所有数据类型)都在事实可变。

答案 3 :(得分:0)

虽然这不是一个答案,但我并不是那么着名的&#39;足以评论或投票。

  1. 上面的@torek关于C constness的可爱篇幅(也是那些在线测试人员在他们的多项选择题中不包含这些原始问题的原因)。

  2. 作为javascript中的初学者,其中的术语是“可变的&#39;意味着(我认为)你可以为它添加属性(使用javascript中的&#39;原型&#39;对象)。

  3. 无论如何,在你在问题中写的代码片段中,语句a = b + c;只更改&#39; a&#39;的使用&#39; b&#39;的和&#39; c&#39;在代码块中的那一点(均为0),所有3个变量都保留其原始地址。因此,您在语句后对赋值变量所做的任何更改都不会影响&#39; a&#39;的值。而在C中,这个事实并不能使它成为“不可变的”,这意味着价值无法改变。