2017-09-02 85 views
0

我已经得到了这个简单的代码,它使用了Jon Eriksen的书中的指针,我试图编译它,但是当我运行它时,gcc给了我编译和分段错误(core dump)时的警告。关于指针的C代码

#include<stdio.h> 

int main(){ 
    int i; 
    int int_array[5] = {1, 2, 3, 4, 5}; 
    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 
    unsigned int hacky_nonpointer; 

    hacky_nonpointer = (unsigned int) int_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(int); // hacky_nonpointer = (unsigned int) ((int *) hacky_nonpointer + 1); 
    } 

    printf("\n\n\n"); 

    hacky_nonpointer = (unsigned int) char_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", hacky_nonpointer, *((char *) hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); 

    } 
} 

输出:

command line: "gcc -g -o pointer_types5 pointer_types5.c" 

pointer_types5.c: In function ‘main’: 

pointer_types5.c:16:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 
    hacky_nonpointer = (unsigned int) int_array; 

pointer_types5.c:20:103: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 
    points to %p which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); 

pointer_types5.c:20:47: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘unsigned int’ [-Wformat=] 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); 

pointer_types5.c:29:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 
    hacky_nonpointer = (unsigned int) char_array; 

pointer_types5.c:35:101: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 
er] points to %p which contains the char %c\n", hacky_nonpointer, *((char *) hacky_nonpointer)); 

pointer_types5.c:35:48: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘unsigned int’ [-Wformat=] 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", hacky_nonpointer, *((char *) hacky_nonpointer)); 



command line: "./pointer_types5" 
Segmentation fault (core dumped) 

some more info about my os: 
uname -a : Linux PINGUIN 4.10.0-33-generiC#37-Ubuntu SMP Fri Aug 11 10:55:28 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 
+1

在64位系统上,指针的大小通常是64位,而int的大小通常是32位。现在您想一下如何将64位值(指针)放入32位变量中。 –

+1

另外,当使用printf使用%p时,你应该直接使用int_array而不是hacky_pointer – leyanpan

+0

好吧,谢谢你们。我能够使它与你的建议一起工作:我从“unsigned int”更改为“long unsigned int”,这样地址就可以放入变量中,我也可以在printf()函数中从“hacky_nonpointer “(void *)”hacky_nonpointer“。 – IDK

回答

1

这个程序是错误的,并在书中给出的建议是obviou狡猾的错误。指针可以转换为指针,但结果是实现定义的。甲指针到空隙可以和被转换为intprt_t,如果这种类型的存在,然后再回到的指针到空隙。这是标准给出的唯一保证。其他的东西可能在一个平台或另一个平台上工作,但它们根本不可移植 - 没有理由将它们用于大型程序。

A %p需要指向无效的指针作为参数。通过int有未定义的行为。

正在尝试节目中的东西不能用C便携表示在所有,但可能是一个更正确的程序是

#include <stdio.h> 
#include <inttypes.h> 

int main(void) { 
    int i; 
    int int_array[5] = {1, 2, 3, 4, 5}; 
    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 
    uintptr_t hacky_nonpointer; 

    hacky_nonpointer = (uintptr_t)(void *)int_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", (void *)hacky_nonpointer, *((int *)(void *)hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(int); 
    } 

    printf("\n\n\n"); 

    hacky_nonpointer = (uintptr_t)(void *)char_array; 

    for(i=0; i < 5; i++){ 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", (void *)hacky_nonpointer, *((char *)(void *)hacky_nonpointer)); 
     hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); 

    } 
} 

然而什么保证hacky_nonpointer = hacky_nonpointer + sizeof(int);会表现得如笔者预期在每平台。然而,它将在许多普通系统上工作,即树莓派,普通ARM体系结构,现代x86-32和x86-64等等。


这本书没有教你C,它教导作者对他认为C应该是什么有缺陷的解释。

0

您的操作系统具有64位架构和编译器是一个32位 - 基于编译器! 由于这个原因,整数和指针的大小不匹配(您可以使用in-built sizeof()函数来检查)。
代替使用整数的,尝试与一些其它数据类型(例如,64位长或长很长,这是重新编译器相关的)和警告(一个或多个)将被移除!

0

错误消息已足够清晰。指针的大小可以大于int的大小。

如果你的编译器支持C99和头<stdint.h>类型uintptr_t然后程序可以像

#include <stdio.h> 
#include <stdint.h> 

int main(void) 
{ 
    int i; 

    int int_array[5] = {1, 2, 3, 4, 5}; 

    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 

    uintptr_t hacky_nonpointer; 


    hacky_nonpointer = (uintptr_t)(void *)int_array; 

    for (i=0; i < sizeof(int_array)/sizeof(*int_array); i++ ) 
    { 
     printf("[hacky_nonpointer] points to %p which contains the integer %d\n", 
      (void *)hacky_nonpointer, *(int *) (void *)hacky_nonpointer); 
     hacky_nonpointer = hacky_nonpointer + sizeof (int); // hacky_nonpointer = (unsigned int) ((int *) hacky_nonpointer + 1); 
    } 

    printf("\n\n\n"); 

    hacky_nonpointer = (uintptr_t) (void *)char_array; 

    for (i=0; i < sizeof(char_array)/sizeof(*char_array); i++) 
    { 
     printf("[hacky non_pointer] points to %p which contains the char %c\n", 
      (void *)hacky_nonpointer, *(char *)(void *) hacky_nonpointer); 
     hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); 
    } 

    return 0; 
} 

它的输出可能看起来像

[hacky_nonpointer] points to 0x7fffffd96da0 which contains the integer 1 
[hacky_nonpointer] points to 0x7fffffd96da4 which contains the integer 2 
[hacky_nonpointer] points to 0x7fffffd96da8 which contains the integer 3 
[hacky_nonpointer] points to 0x7fffffd96dac which contains the integer 4 
[hacky_nonpointer] points to 0x7fffffd96db0 which contains the integer 5 



[hacky non_pointer] points to 0x7fffffd96d90 which contains the char a 
[hacky non_pointer] points to 0x7fffffd96d91 which contains the char b 
[hacky non_pointer] points to 0x7fffffd96d92 which contains the char c 
[hacky non_pointer] points to 0x7fffffd96d93 which contains the char d 
[hacky non_pointer] points to 0x7fffffd96d94 which contains the char e 

C标准(7.20.1.4能够容纳对象指针的整数类型)

以下类型指定与 属性的任何有效的指针的孔隙可以被转换为这种类型的无符号整数类型, 再转换回指向void,结果会比较 等于原始指针:

uintptr_t 

考虑到,根据C标准的功能main不带参数应声明如下

int main(void)