【问题标题】:c - why convert main() argument to constc - 为什么将 main() 参数转换为 const
【发布时间】:2014-10-14 05:21:51
【问题描述】:

(我是C初学者,可能我的问题不是很聪明,但我在问之前已经google了。)

我在git源码中看到了如下代码:

int main(int argc, char **av) {
    const char **argv = (const char **) av;
    // ... more code ...
}

它将char **av转换为const char **argv,我以为是为了让参数不可变,但我写了一个程序,发现两者都argv 和 argv[i] 是可变的。

问题 1:这行代码的目的和优点是什么?

问题 2:const 指针的行为是什么?我用谷歌搜索,但没有找到好的答案。


@更新

我根据答案测试了更多,貌似argv[i][j]是不可变的,但是argvargv[i] 是可变的。

所以指针上的 const 使得原始值不可变,但指针本身仍然是可变的。

因此我猜来自 git 的代码的主要目的也是为了防止更改原始参数。

测试代码

#include <stdio.h>

int main(int argc, char * av[]) {
    // modify value pointed by a non-const pointer - ok
    av[0][0] = 'h';
    printf("argv[0] = %s\n", av[0]);

    // modify const pointer itself - ok
    const char **argv = (const char **) av;
    argv[0] = "fake";
    printf("argv[0] = %s\n", argv[0]);
    char *arr[] = {"how", "are", "you"};
    argv = (const char **)arr;
    printf("argv[0] = %s\n", argv[0]);


    // modify the value itself which is pointed by a const pointer - bad, an error will be thrown,
    /*
    argv[0][0] = 'x';
    printf("argv[0] = %s\n", argv[0]);
     */

    return 0;
}

当前代码可以编译和运行,没有警告或错误,但如果取消注释最后的 2 行注释,那么编译时会抛出以下错误:

错误:分配只读位置“**argv”

【问题讨论】:

    标签: c pointers constants


    【解决方案1】:

    1) 稍后使用 const 指针访问参数实际上没有任何意义,除非确保它们没有被更改。

    2) const 指针的目的是确保它们不会在整个代码中更改。你可以没有它们,但它有助于避免错误。

    【讨论】:

      【解决方案2】:

      实际上它在这里不是很有用(如果编译器是optimizing,生成的代码不会有太大变化)。

      但是,argv 是不可变的,因此编译器会例如将像这样的赋值捕获为错误

      argv[1][0] = '_'; // wrong
      

      无法分配const 事物。所以无法分配const 指针,指向const 的指针意味着取消引用的指针是无法分配的位置。 (你可以混合使用:有一个const 指向const 的指针)

      顺便说一句,main  - 在标准中 C99- 是一个非常特殊的功能。您不能以任意方式声明它(它几乎总是应该声明为int main(int, char**)int main(void) ....)并且您可能不能调用它(例如它不能是递归的),但这在 C 和 C++ 中可能不同.所以声明int main (int, const char**) 是非法的。

      【讨论】:

      • 看起来指向的值本身是不可变的,但是指针是可变的。
      • 一个 const 指针是不可变的。只能在定义时设置。
      • 你是如何测试它的?可以发一下代码吗?
      • main 的实际原型是int main(int argc, char* argv[]);,但许多操作系统使用int main(int argc, const char* argv[]);,因为它们(技术上)是允许的(C 标准没有指定 argv 是否必须是可写的)。
      猜你喜欢
      • 2010-09-09
      • 1970-01-01
      • 1970-01-01
      • 2012-07-09
      • 2011-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多