我有这个简单的代码,它使用了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
答案 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 )