-3

Could somebody explain to me why the ints that are taken in from the user with scanf() are stored in addresses that are 8h apart even though the size of an int on my 64 bit machine in 4 bytes? It is to with with alignment in memory?

#include <stdio.h>
void main() {

    int *a;
    int i, n;



    printf(" Input the number of elements to store in the array : ");
    scanf("%d",&n);

    printf(" Input %d number of elements in the array : \n",n);

    printf("size of on int is %d\n", sizeof(i));

    for(i=0;i<n;i++) {
        printf(" element - %d : ",i+1);
        printf("address of a is %p\n", &a+i);
        scanf("%d",a+i);
    }

   return 0;

}


 Input the number of elements to store in the array : 3
 Input 3 number of elements in the array : 
size of on int is 4
 element - 1 : address of a is 0x7ffda5cf8750
6
 element - 2 : address of a is 0x7ffda5cf8758
5
 element - 3 : address of a is 0x7ffda5cf8760
2
horizon
  • 31
  • 1
  • 4
  • 1
    `%d` expects an `int`. `sizeof` yields a `size_t` -> undefined behaviour. – too honest for this site Jun 14 '17 at 14:01
  • 1
    `&a` takes the address of a pointer, and the pointer needs 8 bytes. You have other problems in this code to worry about, like writing to invalid locations (`a` isn't pointing anywhere valid!) –  Jun 14 '17 at 14:01
  • 1
    `printf("address of a is %p\n", (void *)(a+i));` will show the pointer going up by `sizeof(int)` (4). – Ian Abbott Jun 14 '17 at 14:19

1 Answers1

5
#include <stdio.h>
void main() {

    int *a;
    int i, n;

Is there any code following you omitted? If not, a is now an uninitialized pointer with indeterminate value.

    printf("address of a is %p\n", &a+i);

Here you take the address of a using the & operator. The result is a pointer to a, IOW a pointer to a pointer. The size of a pointer on a 64bit system is 8, so this should answer your question.

    scanf("%d",a+i);

and here you write to some "random" memory location. This is undefined behavior


For your reference, the fixed program for what you seem to want to do:

#include <stdio.h>
#include <stdlib.h> // <- needed for malloc()/free()

// use a standard prototype, void main() is not standard:
int main(void) {

    int *a;
    int i, n;

    printf(" Input the number of elements to store in the array : ");
    if (scanf("%d",&n) != 1)
    {
        // check for errors!
        return 1;
    }

    // allocate memory:
    a = malloc(n * sizeof(int));

    for(i=0;i<n;i++) {
        printf(" element - %d : ",i+1);
        if (scanf("%d", a+i) != 1)
        {
            // again, check for errors!
            return 1;
        }
    }

    // [...]

    // when done, free memory:
    free(a);

    return 0;
}

For learning how to do the input more robustly, read documentation on scanf(), fgets(), strtol() ... I prepared a little document, but there are a lot of other resources available online, e.g. this FAQ on SO.

  • Also, if you are using a Microsoft compiler, look at safer versions of scanf (e.g. s_scanf) that prevent buffer overflows. – Neil Jun 14 '17 at 14:19
  • 3
    @Neil no, `scanf_s` is completely unnecessary and just an attempt on vendor lock-in. For conversions to strings, just use `scanf()` with proper field-widths. –  Jun 14 '17 at 14:19
  • Really? so there is no buffer overflow possible in scanf("%s", charArray) ? – Neil Jun 14 '17 at 14:21
  • @Neil 1) The MS libs bounds checking functions are not all compatgible with the standard functions - despite the same names, which is a complete no-go already. 2) You can limit the number of characters read with the normal function. Nothing gained. – too honest for this site Jun 14 '17 at 14:22
  • @Neil the solution is not `scanf_s()` but `scanf("%19s", ...)` if array size is 20. Or better yet, use `fgets()` and similar. –  Jun 14 '17 at 14:22
  • I agree about `fscanf_s` being unnecessary. However, there are standard functions with those names (see my comment above). Problem is they are optional and basically unnecessary, thus not often implemented. – too honest for this site Jun 14 '17 at 14:25
  • @Olaf which standard function are you talking about? I'm pretty sure `scanf_s()` doesn't exist in the standard ... –  Jun 14 '17 at 14:27
  • Considering the number of posts here which mis-use `scanf_s()` it IMO is no safer than `scanf()`. – Weather Vane Jun 14 '17 at 14:27
  • Which is better, using something where the width of the input is completely separate to the destination (e.g. in a format string), or something where the destination is inseparable (e.g. in a sizeof) ? – Neil Jun 14 '17 at 14:29
  • @FelixPalmen: Et voila: http://port70.net/~nsz/c/c11/n1570.html#K.3.5.3.4 – too honest for this site Jun 14 '17 at 14:29
  • @FelixPalmen: Annex K of ISO/IEC 9899:2011 contains (a slight superset of) the functions defined in TR 24731-1. They are an optional feature in C11. There is a proposal to remove them from the next revision of the C standard. See [Do you use the TR 24731 'safe' functions](https://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions) for information on these — and links to the paper proposing they are removed. The functions are not widely implemented. – Jonathan Leffler Jun 14 '17 at 14:30
  • Uhhh, `rsize_t` -- I see the problem. Link this by accident with an MS C library ;) Thanks for the links! –  Jun 14 '17 at 14:34