I’ve got this simple code that plays with pointers taken from Jon Eriksen’s book that I’m trying to compile but gcc gives me warnings in compilation and segmentation fault (core dumped) when I run it.
#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 %dn", hacky_nonpointer, *((int *) hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(int); // hacky_nonpointer = (unsigned int) ((int *) hacky_nonpointer + 1); } printf("nnn"); hacky_nonpointer = (unsigned int) char_array; for(i=0; i < 5; i++){ printf("[hacky non_pointer] points to %p which contains the char %cn", hacky_nonpointer, *((char *) hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); } }
Output:
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 %dn", 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 %dn", 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 %cn", 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 %cn", 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
Advertisement
Answer
This program is wrong, and the advice given in the book is obviously wrong, too. A pointer can be converted to an integer type, but the result is implementation-defined. A pointer-to-void can be converted to intprt_t
/uintptr_t
, if they exist, and then back again to a pointer-to-void and you would get back the original pointer. This is the only guarantee given by the standard. Other things might work on one platform or another, but they wouldn’t be portable at all – there is no reason why you’d use them in a large program.
A %p
requires a pointer-to-void as an argument. Passing an int
has undefined behaviour.
The things that are attempted in the program cannot be expressed portably in C at all, but possibly a more correct program would be
#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 %dn", (void *)hacky_nonpointer, *((int *)(void *)hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(int); } printf("nnn"); hacky_nonpointer = (uintptr_t)(void *)char_array; for(i=0; i < 5; i++){ printf("[hacky non_pointer] points to %p which contains the char %cn", (void *)hacky_nonpointer, *((char *)(void *)hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(char); // hacky_nonpointer = (unsigned int *) ((char *) hacky_nonpointer + 1); } }
however nothing guarantees that hacky_nonpointer = hacky_nonpointer + sizeof(int);
would behave as author intended on every platform. It will however work on many ordinary systems, i.e. Raspberry Pi, ordinary ARM architectures, modern x86-32 and x86-64 and many more.
This book doesn’t teach you C, it teaches author flawed interpretation about what the C should be in his opinion.