2015-10-04 83 views
0

我在写这个程序来练习C语言编程,这是我的代码:C编程:铸造“无效指针”指向结构

#include <stdio.h> 
#include <stdlib.h> 
struct s1 { 
     int i; 
     void * p; 
    }; 
static struct s1 *dmk; 
int main(void) { 

    int tong(int a, int b); 
    int (*tinh)(int,int); 

    struct s2 { 
     int num; 
     int (*cal)(int a, int b); 
    }; 
    if(dmk->p == NULL) 
    { 
     printf("NULL ALERT\n"); 
    } 
    struct s2 *cl = dmk->p; 
    cl->cal = tong; 

    tinh = ((struct s2 *)(dmk->p))->cal; 
    printf("tinh 2, 4 ra %d\n",tinh(2,4)); 
    puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */ 
    return EXIT_SUCCESS; 
} 

int tong(int a, int b) 
{ 
    return a + b; 
} 

当我编译它,它没有表现出任何错误或警告。但是当我运行程序时,终端告诉我“核心转储”并没有显示任何结果接受“NULL ALERT”。谁能解释我为什么失败?非常感谢。

回答

3
if(dmk->p == NULL) 

dmk 未初始化 初始化为NULL,指出“没有地方”,所以去引用它调用未定义行为失败。之后会发生任何事情。

+0

在我引用的陈述中用' - >'调用UB是个问题。编码器方面出现“*失败*”。 @ T.J.Crowder – alk

+1

实际上'dmk' **被**初始化,因为它是一个全局变量。问题:它是一个_null pointer_。 – Olaf

+0

@Olaf:正确,修正,谢谢。 – alk

2

底线是你在做错的事情是在使用它们之前不把东西分配给你的各种指针。

您的dmk是全球性的,因此其初始值为NULL。你永远不会改变这个价值。

后来,你读了dmk->p。您现在处于未定义行为(UB)领域。该程序可能很容易出错,因为您正在从NULL指针读取数据。

显然它没有,因为你看到你的消息NULL ALERT,所以我们继续。

然后你这样做:

struct s2 *cl = dmk->p; 
cl->cal = tong; 

在第二行有,cl完全是不确定的。这可能是垃圾,可能是NULL,无论如何,因为你进入了UB领土。然后你解引用它并写入结果。你可能试图在任何地方写字。写入随机指针(或指针NULL)往往会导致核心转储和其他坏事情发生。

在使用它们之前,您需要为指针实际赋值。

1

您不要在代码中初始化dmk。那个dmk-> p是NULL是纯粹的运气。什么事情都可能发生。

您需要使用例如malloc()为您的结构分配内存,并正确初始化成员。

+3

实际上'dmk' **被**初始化,因为它是一个全局变量。问题:它是一个_null pointer_。 – Olaf

2

dmk是一个全球性的(亦称静态的(这是相关static关键字!),可变的,因此它被初始化为空指针。你不改变这个值,所以dkms->p取消引用一个空指针,它调用未定义行为(UB)。

所以从这里,这是炒作,因为UB意味着任何事情都有可能发生

显然printf通过,可能是因为地址可以被读取。以下写入OTOH失败,生成系统消息。