我有以下代码:

typedef struct S1 S1_t;
struct S1
{
  uint8_t *ptr1;
  uint8_t **ptr2;
};

void get_ptr1(const S1_t *s1, uint8_t const **ptr1)
{
  *ptr1= s1->ptr1;
}

void get_ptr2(const S1_t *s1, uint8_t const *const **ptr2)
{
  *ptr2 = s1->ptr2;
}

如果我让它保持原样,我会收到GCC编译器对函数get_ptr2发出的以下警告:

assignment to ‘const uint8_t * const*’ {aka ‘const unsigned char * const*’} from incompatible pointer type ‘uint8_t **’ {aka ‘unsigned char **’}

为了使警告静音,在将其赋给ptr2之前,我必须将其强制转换为s1->ptr2:

void get_ptr2(const S1_t *s1, uint8_t const *const **ptr2)
{
  *ptr2 = (const uint8_t *const *)s1->ptr2;
  return 0;
}

我不明白为什么我需要在这里做这个转换操作,当我不需要在get_ptr1中做(const uint8_t *)转换时?

我在这里的目标是实现 struct S1‘S成员的Getter函数,我想确保获取这些成员的函数不能修改它们.因为我在这里做了一些危险的事情,所以编译器会向我发出警告吗?

我有-wall-wextra编译选项标志启用.

推荐答案

虽然允许将指向非const类型的指针赋给指向const类型的指针,但这只适用于第一个"级别"的指针.如果允许这样做,则可能允许修改const个对象.

例如:

const char c = 1;
const char *p1 = &c;
char *p2;
char **pp1 = &p2;
const char **pp2 = pp1;    // invalid char ** to const char ** conversion
*pp2 = p1;                 // p2 now points to c (no warning!)
*p2 = 2;                   // modifying a const object (no warning!), UB

在上面的例子中,与你的情况略有不同,因为只有"外部水平"是const. 如果pp2被定义为const char * const *pp2,那么这将是不可能的,因为行*pp2 = p1;将包含错误. 这实际上是C标准中的一个缺陷,你的情况是不允许的,因为目标类型中的每个指针级别都是const限定的.

像您所做的那样,应用强制转换是对这种情况的适当修复.

C++相关问答推荐

如何确保内存分配在地址附近?

以c格式打印时间戳

如何在C中只使用一个带双方括号([i][j])访问语法的malloc来分配动态大小的2d数组?

如何正确地索引C中的 struct 指针数组?

自定义应用程序上的日志(log)轮换问题

使用额外的公共参数自定义printf

以前版本的tty_ldisc_ops.ioctl()是否也需要文件参数?

将整数的.csv文件解析为C语言中的二维数组

Win32API Wizzard97 PropSheet_SetWizButton不工作

C是否用0填充多维数组的其余部分?

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

如何在C中只对字符串(包含数字、单词等)中的数字进行重复操作?

为 struct 中的数组动态分配内存时出错

如何使用唯一数字对整型进行分区

不同原型的危险C函数是可能的

覆盖读取函数,但当文件描述符为3或4时,我有问题

C语言中MPI发送接收字符串时出现的分段错误

为什么GCC-O1优化破解了这个代码,为了一个GameBoy高级只读存储器而修改了VRAM的循环?

具有正确标头的C struct 定义问题

C: NULL>;NULL总是false?