c编程中常量的更新

c编程中常量的更新,c,constants,C,Constants,如果不想更改变量的值,可以在C语言中将其声明为常量 #include <stdio.h> int c1() { int *a; const int b; a=&b; printf("*a=%d, b=%d\n",*a, b); *a = *a + 1; //b = b + 1; printf("*a=%d, b=%d\n", *a, b); //return ; } main() { printf("C=

如果不想更改变量的值,可以在C语言中将其声明为常量

#include <stdio.h>
int c1()
{
  int *a;
  const int b;

  a=&b;

  printf("*a=%d, b=%d\n",*a, b);

  *a = *a + 1;
  //b = b + 1; 

  printf("*a=%d, b=%d\n", *a, b);

//return ;
}

main()
{       
        printf("C=%d\n", c1());
}
这是人们所期望的。
但是如果我们声明一个指针变量,它指向const变量,并且您增加指针变量指向的“值”,那么编译器不会抱怨。为什么?

这个

a = &b;
在C中不允许。代码包含约束冲突,即它不是有效的C代码,是一个错误。任何兼容的C编译器都会立即发出此问题的诊断消息。如果你的编译器没有抱怨,你的编译器就坏了

6.5.16.1简单作业
约束
1以下其中一项应有效:
[…]
-左操作数具有原子、限定或非限定指针类型,并且(考虑到左值转换后左操作数将具有的类型),两个操作数都是指向兼容类型的限定或非限定版本的指针,,并且左指的类型具有右指的类型的所有限定符
[……]

在您的情况下,LHS上的pointed类型没有RHS上pointed类型的所有限定符。您的代码包含约束冲突,即硬语言错误

另外,您的
main()
也无效。应该是
intmain()
,或者更好的
intmain(void)

这会调用未定义的行为

引用

6.7.3类型鉴定人

1480如果试图通过使用具有非常量限定类型的左值来修改具有常量限定类型的对象,则该行为是未限定的

所以它实际上取决于编译器对它做了什么

我的编译器给出了

[Error] invalid conversion from 'const int*' to 'int*' [-fpermissive]
但是你的结果不同,因为你的编译器只是试图理解它。因为这是一种未定义的行为,所以没有必要去理解它

a=&b是不合法的: 正如其他人所指出的,
a=&b
不是合法的C。然而,这并不是因为不允许您将
const int*
(指向常量
int
)的指针转换为
int*
(指向
int
)的指针;这是因为你不被允许隐式地这样做。如果您明确表示要转换它,可以使用强制转换进行转换。(如果在没有强制转换的情况下执行此操作时,编译器没有向您发出警告消息,则应为编译器打开更多警告消息。如果编译器仍然没有向您发出警告,则说明它是一个错误的编译器。)

具体而言,C 2011标准第6.5.16.1条第1款【草案N1570】列出了转让声明必须满足的约束条件。关于这种情况,他们基本上说
const int*
只能分配给
const int*
而不能分配给
int*

a=(int*)和b是合法的: 但是,您可以编写
a=(int*)&b
。这满足6.5.4.1中列出的铸件约束条件。6.3.2.3表示,只要指针与目标类型正确对齐,就可以将指向对象类型的指针转换为指向任何其他对象类型的指针

但是,您不能使用指针;您不能使用
*a=3
,因为此时您正试图更改使用
const
定义的对象。6.7.3.6表示执行此操作时的行为未定义

由于C历史记录,const是灵活的: 那么为什么C允许它呢?嗯,C语言在被添加到语言中之前已经开发和使用了很多年。它必须在中进行改装,这要求允许现有代码工作,并且不破坏语言的其他特性。
const
的一个特点是,尽管一个例程可能会被传递一个
const int*
,但它指向的实际对象不一定是用
const
定义的。例如,我可以设置
intx=7
,然后将
&x
传递给参数为
const int*p
的例程。这意味着例程不会更改
p
所指向的内容,但并不意味着其他例程不会更改它

标准的
strchr
功能显示了一个问题。这被声明为
char*strchr(const char*s,int c)。它是用
const char*s
参数声明的,因为我们希望能够毫无怨言地将指针传递给
const char
。由于参数是
const char*
,因此允许传递
const char*
char*
。这是有意义的,因为
strchr
只查找字符串中的内容;它不会更改字符串

假设我有一个非常量字符串
charfoo[]=“abcdef”
。我可以使用
strchr
通过使用
char*p=strchr(s,'d')
在其中搜索
'd'
。但是我得到的结果是
char*
,而不是
const char*
strchr
接受了一个
const char*
,但随后将其更改为
char*

在这种情况下,这是可行的。我传递了一个
char*
,它被自动转换为函数调用的
const char*
,我得到了一个
char*
,它对我的非常量字符串是合法的。但是,C语言中的
constchar*
指针必须更改为
char*
这一有趣的操作实际上是由其历史造成的缺陷

添加常量和删除常量的往返是合法的: 还有一种情况:

  • 我编写了一个库供其他程序使用

  • 库中的一个例程准备了一些数据供以后使用,比如some
    struct foo中的数据。此例程分配内存,计算数据,并返回一个
    const struct foo*
    。它返回一个
    const
    指针,因为
    int *a;
    const int b=5;
    
    a=&b;
    
    [Error] invalid conversion from 'const int*' to 'int*' [-fpermissive]