解引用空指针

5
我有以下代码:

我有以下代码:

#include <inttypes.h>
#include <stdlib.h>
struct a
{
  void *p;
};

int main(void)
{
  struct a *ptr = malloc(sizeof(struct a));
  ptr->p = malloc(sizeof(uint8_t));
  *((uint8_t *) ptr->p) = 2;
  return 0;
}

我在解除引用之前将空指针转换为void指针以避免警告。

警告:解除引用'void *'指针

这样做是否违反了任何规则,或者这段代码是否正确?


你对可能被违反的规则有什么怀疑? - M.M
2
如果没有特定的原因,为什么p的类型不是uint8_t*,那么这段代码就很糟糕。 - Staven
2
@Staven先生,这不是我在代码库中实际拥有的代码。只是试图做类似的事情。假设结构体中已经有一个void *p,并且不能干扰该结构体但想要使用它。这不是糟糕的代码。 - Gopi
2
你应该 #include <stdlib.h> - M.M
@alk 同意。我的问题主要是关于强制转换部分。是的,需要头文件 :) - Gopi
显示剩余5条评论
2个回答

6

是的,这段代码是合法的,不会引起未定义的行为(除非malloc返回NULL)。


3
根据标准规定,这段代码看起来没问题。可以使用指向字符类型的指针指向对象而不违反别名规则。
引用标准章节§6.3.2.3:
[...] 当将指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低地址字节。对结果的连续递增,直到对象的大小,会产生指向对象其余字节的指针。

1
即使它不是字符类型的指针,代码也可以正常运行。由于该对象没有声明类型,因此用于写入的有效类型是您使用的写入类型(读取的有效类型是上次写入对象的类型)。在这个例子中我们只进行写操作,因此我们设置了有效类型。 - M.M
@MattMcNabb 当然可以。我在想,如果 p 不是 void * 类型,那么将其转换为 char *(或等效类型)并进一步使用也是被定义的,对吧? - Sourav Ghosh
nb: 我认为uint8_t不一定是字符类型(https://dev59.com/O2cs5IYBdhLWcg3wp133) - Giorgi Moniava
@SouravGhosh p 的类型无关紧要;对象的类型才是重要的。该对象是由 malloc 创建的,因此它没有类型。 - M.M
@MattMcNabb 对不起,我有点困惑。我以为 p 的类型除了是 void * 之外还有其他的影响。比如,如果我们有 float *p = malloc(sizeof*p); 然后我们做 *((int *)p) = 5; 这种情况是否被定义了呢? - Sourav Ghosh
@SouravGhosh,是的,只要sizeof(int) <= sizeof(float)就可以定义良好。通过*(int *)p写入将malloc分配的对象的有效类型设置为int。随后读取*p将是未定义的。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接