关于指针的C代码

时间:2017-09-02 11:09:02

标签: c linux pointers gcc casting

我有这个简单的代码,它使用了Jon Eriksen的书中的指针,我正在尝试编译,但是当我运行它时,gcc会在编译和分段错误(核心转储)中给出警告。

#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

3 个答案:

答案 0 :(得分:1)

这个程序错了,书中给出的建议显然是错误的。指针可以转换为指针,但结果是实现定义的。 指向void的指针可以转换为intprt_t,如果存在此类型,,然后再返回到指向void的指针。这是标准给出的唯一保证。其他东西可能在一个平台或另一个平台上运行,但它们根本不可移植 - 没有理由在大型程序中使用它们。

%p需要指向void的指针作为参数。传递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);在每个平台上都表现为作者的意图。然而,它将适用于许多普通系统,即Raspberry Pi,普通ARM架构,现代x86-32和x86-64等等。

这本书并没有教你C,它教导作者在他看来C应该是什么的有缺陷的解释。

答案 1 :(得分:0)

您的操作系统具有64位架构,编译器是基于32位的编译器! 因此,整数和指针的大小不匹配(您可以使用内置的sizeof()函数进行检查)。
不要使用整数,而是尝试使用其他一些数据类型(例如64位长或长,再次依赖于编译器),警告将被删除!

答案 2 :(得分:0)

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

如果你的编译器在标题uintptr_t中支持C99和类型<stdint.h>,那么程序可能看起来像

#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的指针转换为此类型的属性,   然后转换回指向void的指针,结果将进行比较   等于原始指针:

uintptr_t

考虑到根据C标准,不带参数的函数main应声明为

int main( void )