有没有办法保护变量在运行时在C中被修改?

时间:2015-06-15 12:35:11

标签: c variables constants

我想知道在初始化之后是否有任何方法可以保护变量以进行修改(例如" constantize"运行时的变量)。例如:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int v, op;
    scanf( "%d", &op );
    if( op == 0 )
        v = 1;
    else
        v = 2;
// here transform v to a constant...
    .
    .
// ...and that any attempt to modify v yields to an error.
    .
    .
    return EXIT_SUCCESS;
}

4 个答案:

答案 0 :(得分:3)

您可以将输入的结果设为const,如下所示:

int func()
{
    int op = 0;
    scanf( "%d", &op );
    if( op == 0 )
        return 1;
    else
        return 2;
}

int main()
{
    const int v = func();
    // ...
}

NB。当然,没有办法防止程序中稍后发生的未定义行为发生变化v(因为根据定义,未定义的行为可能会产生任何影响)。

答案 1 :(得分:1)

是:考虑您的代码:

<强> foo.h中:

void do_something(int arg);

<强> foo.c的:

#include "foo.h"

void do_something(int arg)
{
    // implement
    //
    // Here "arg" is completely under your control.
}

<强> foo_test.c:

#include "foo.h"

// add unit tests for do_something

<强> main.c中:

#include <stdio.h>
#include <stdlib.h>
#include "foo.h"

int main(void)
{
    int op;
    if (scanf("%d", &op) != 1) { abort(); }

    do_something(op == 0 ? 1 : 2);
}

现在从代码中可以清楚地看到do_something的函数参数是函数的私有和本地函数,并且不会受到调用之上任何内容的影响。

答案 2 :(得分:1)

在初始化之后阻止全局变量被修改的唯一方法是声明const

const int i = 5;

但是,如上所示,这需要使用定义进行初始化。无法从程序代码初始化它或使用在编译时计算的常量表达式以外的其他方法。

请注意,虽然你可以强制转换const,但这会导致 undefined bahaviour ,并且很可能导致问题,因为const变量可能被放入程序的只读存储区。

如果你需要对这样的变量进行访问控制,你必须把它作为static放入一个函数中(在第一次调用时初始化),或者 - 更好的单独一个模块/编译单元(也称为static)。然后使用显式的setter / getter函数:

"wrapper.h":

#ifndef WRAPPER_H
#define WRAPPER_H

extern void set_once(int v);
extern int get_value(void);

#endif
"wrapper.c":

#include <stdbool.h>
#include "wrapper.h"

static struct {
    bool is_set;    // guaranteed false on startup
    int value;
} my_var;

void set_once(int v)
{
    if ( !my_var.is_set )
        my_var.value = v;
    else
        ; // report an error, e.g. abort()
}

int get_value(void)
{
    if ( !my_var.is_set )
        return my_var.value;
    // report an error, e.g. abort()
}
"main.c"

#include "wrapper.h"

int main(void)
{
    set_once(5);
    int i = get_value();
}

这样,如果您使用未初始化的值或尝试多次设置它,您将收到运行时错误。请注意,该标志依赖于全局变量初始化为0(保证评估false)。 虽然您可能只是忽略多个集合,但抓住并报告是一种很好的做法,至少在调试/测试期间(例如使用assert)。

修改

上述方法适用于全局变量。如果要保护多个变量,可以对其进行修改,例如函数采用指向结构的指针。如果要使用不同的类型,请将标志打包到其自己的结构中,并将其作为第一个匿名字段添加到要保护的每个类型的一个结构类型中。如果gcc-extensions可用且允许,请查看-fplan9-extensions。使用不透明指针可以避免意外的外部修改。

但是,对于局部变量,请使用@ MattMcNabb的版本。

答案 3 :(得分:0)

不,永远不会。

你可以把它变成const,但这更像是一个轻微的暗示,可以毫不费力地抛弃它。此外,如果你有指向某个东西的指针,你可以随时通过直接内存访问来改变它。

您也可以将其隐藏在管理对它的写入权限的类中,但是您遇到的情况与第一种情况相同 - 您有指向它的指针。