常量和指向指针的指针 [英] constness and pointers to pointers

查看:26
本文介绍了常量和指向指针的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 const 关键字非常困惑.我有一个接受字符串数组作为输入参数的函数和一个接受可变数量参数的函数.

I'm very much confused about the const keyword. I have a function accepting an array of strings as input parameter and a function accepting a variable number of arguments.

void dtree_joinpaths(char* output_buffer, int count, ...);
void dtree_joinpaths_a(char* output_buffer, int count, const char** paths);

dtree_joinpaths 在从参数列表构建一个字符串数组后,在内部调用 dtree_joinpaths_a.

dtree_joinpaths internally invokes dtree_joinpaths_a after it has built an array of strings from the argument list.

void dtree_joinpaths(char* output_buffer, int count, ...) {
    int i;
    va_list arg_list;
    va_start(arg_list, count);
    char** paths = malloc(sizeof(char*) * count);
    for (i=0; i < count; i++) {
        paths[i] = va_arg(arg_list, char*);
    }
    va_end(arg_list);
    dtree_joinpaths_a(output_buffer, count, paths);
}

但是 gcc 编译器给了我以下错误信息:

But the gcc compiler gives me the following error message:

src/dtree_path.c: In function 'dtree_joinpaths':
src/dtree_path.c:65: warning: passing argument 3 of 'dtree_joinpaths_a' from incompatible pointer type

当我将 char** paths = malloc(count); 更改为 const char** paths = malloc(count); 时,此错误不再出现.我不明白的是,那个

When I change char** paths = malloc(count); to const char** paths = malloc(count);, this error is not showing up anymore. What I don't understand is, that

  1. 我认为指向地址的指针总是可以转换为 const 指针,但反过来不行(imo 就是这样).
  2. 此示例有效:http://codepad.org/mcPCMk3f

我做错了什么,或者我的误解在哪里?

What am I doing wrong, or where is my missunderstanding?

我的目的是让输入数据的内存对于函数来说是不可变的.(在本例中为 paths 参数).

My intent is to make the memory of the input data immutable for the function. (in this case the paths parameter).

推荐答案

char ** -> const char** 是一个危险"转换的原因是以下代码:

The reason char ** -> const char** is a "dangerous" conversion is the following code:

const char immutable[] = "don't modify this";

void get_immutable_str(const char **p) {
    *p = immutable;
    return;
}

int main() {
    char *ptr;
    get_immutable_str(&ptr); // <--- here is the dangerous conversion
    ptr[0] = 0;
}

上面的代码试图修改一个不可修改的对象(const char 的全局数组),这是未定义的行为.这段代码中没有其他候选者可以将某些内容定义为坏",因此常量安全性表明指针转换是坏的.

The above code attempts to modify a non-modifiable object (the global array of const char), which is undefined behavior. There is no other candidate in this code for something to define as "bad", so const-safety dictates that the pointer conversion is bad.

C 不禁止转换,但 gcc 会警告您这是不好的.仅供参考,C++ 确实禁止转换,它比 C 具有更严格的常量安全性.

C does not forbid the conversion, but gcc warns you that it's bad. FYI, C++ does forbid the conversion, it has stricter const-safety than C.

我会在示例中使用字符串文字,除了 C 中的字符串文字一开始是危险的"——你不能修改它们,但它们的类型是 array-of-char 而不是 array-of-const char.这是历史原因.

I would have used a string literal for the example, except that string literals in C are "dangerous" to begin with -- you're not allowed to modify them but they have type array-of-char rather than array-of-const char. This is for historical reasons.

我认为指向地址的指针总是可以转换为常量指针

I thought a pointer to an address can always be casted to a const pointer

指向非常量 T 的指针可以转换为指向常量 T 的指针.char ** -> const char** 不是这种模式的例子,因为如果 Tchar * 那么 const Tchar * const,而不是 const char *(此时不写 const 在左边:写 char const * 并且你不会期望它与 T const 相同,其中 T 是 char *).

A pointer-to-non-const-T can be converted to a pointer-to-const-T. char ** -> const char** isn't an example of that pattern, because if T is char * then const T is char * const, not const char * (at this point it's probably worthwhile not writing the const on the left any more: write char const * and you won't expect it to be the same as T const where T is char *).

您可以安全地将 char ** 转换为 char * const *,并且(由于需要的不仅仅是简单规则的原因)您可以安全地转换 char **char const * const *.

You can safely convert char ** to char * const *, and (for reasons that require a little more than just the simple rule) you can safely convert char ** to char const * const *.

这篇关于常量和指向指针的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆