2

I spent some time trying to understand what was going on with this code but in the end I couldn't fully figure it out.

void knock_knock(char *s){
 while (*s++ != '\0')
  printf("Bazinga\n");
}

int main() {
 int data[5] = { -1, -3, 256, -4, 0 };
 knock_knock((char *) data);
 return 0;
}

I was surprised when I saw it didn't print 'Bazinga' 5 times, but 8. My next thought was that it was just iterating over the length of the pointer, so it would make sense that it printed 8 times. But, then I changed the first number of the array from -1, to check whether the data truly was relevant or not, and this is where I was confused. It didn't print 8 times anymore, but just once. Why?

miken32
  • 42,008
  • 16
  • 111
  • 154
Khryus
  • 347
  • 3
  • 12
  • 1
    The function is pointing int values (4 bytes) with a char pointer that point chars (1 bytes)..... – LPs Feb 02 '17 at 10:35
  • 1
    Add `printf ("%08X - %08X - %08X\n", data[0], data[1], data[2]);` before the function call and see the output... – LPs Feb 02 '17 at 10:36
  • 1
    Doesn't this invoke undefined behaviour? – George Feb 02 '17 at 10:38
  • Next time you ask a question, please avoid to write a [wall of text](http://uncyclopedia.wikia.com/wiki/Wall_of_Text). – Jabberwocky Feb 02 '17 at 10:42
  • 2
    @George I don't think so, I think accessing stuff as `char` is generally OK. Don't quote me on that though, haven't read the standard this morning. :) – unwind Feb 02 '17 at 10:42
  • @unwind alright, cheers for the response :) – George Feb 02 '17 at 10:49
  • Sorry for the wall of text, just wanted to explain what I tried. If you didn't want to read the wall of text you could have just answered the question in the title and it would've been perfectly fine either way... Anyways thanks for taking the time to answer, I'll take a look now. – Khryus Feb 02 '17 at 10:50
  • @George I don't think so: is, for example, how `memcpy` & so. work. Mayby is violating strict aliasing rules. – LPs Feb 02 '17 at 10:50
  • "I saw it didn't print 'Bazinga' 5 times" --> Why did you expect 5 versus maybe 4? – chux - Reinstate Monica Feb 02 '17 at 11:46

3 Answers3

7

Using the following code

#include<stdio.h>

void knock_knock(char *s)
{
    while (*s++ != '\0')
        printf("Bazinga\n");
}

int main()
{
    int data[5] = { -1, -3, 256, -4, 0 };
    printf("%08X - %08X - %08X\n", data[0], data[1], data[2]);
    knock_knock((char *) data);
    return 0;
}

You can see that HEX values of data array are

FFFFFFFF - FFFFFFFD - 00000100

Function knock_knock print Bazinga until the pointed value is 0x00 due to

while (*s++ != '\0')

But the pointer here is pointing chars, so is pointing a single byte each loop and so, the first 0x00 is reached accessing the "first" byte of third value of array.

LPs
  • 16,045
  • 8
  • 30
  • 61
4

You need to look at the bytewise representation of data in the integer array data. Assuming an integer is 4 bytes, The representation below gives the numbers in hex

-1    -->  FF FF FF FF
-3    -->  FF FF FF FD
 256  -->  00 00 01 00
 -4   -->  FF FF FF FC
 0    -->  00 00 00 00

The array data is these numbers stored in a Little- Endian format. I.e. the LSbyte comes first. So,

data ={FF FF FF FF FD FF FF FF 00 01 00 00 FC FF FF FF 00 00 00 00};

The function knock_knock goes through this data bytewise and prints Bazinga for every non-zero. It stops at the first zero found, which will be after 8 bytes.

(Note: Size of Integer can 2 or 8 bytes, but given that your pointer size is 8 bytes, I am guessing that size of integer is 4 bytes).

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
1

It is easy to understand what occurs here if to output the array in hex as a character array. Here is shown how to do this

#include <stdio.h>

int main(void) 
{
    int data[] = { -1, -3, 256, -4, 0 };
    const size_t N = sizeof( data ) / sizeof( *data );

    char *p = ( char * )data;

    for ( size_t i = 0; i < N * sizeof( int ); i++ ) 
    {
        printf( "%0X ", p[i] );
        if ( ( i + 1) % sizeof( int ) == 0 ) printf( "\n" );
    }

    return 0;
}

The program output is

FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 
FFFFFFFD FFFFFFFF FFFFFFFF FFFFFFFF 
0 1 0 0 
FFFFFFFC FFFFFFFF FFFFFFFF FFFFFFFF 
0 0 0 0 

So the string "Bazinga" will be outputted as many times as there are non-zero bytes in the representations of integer numbers in the array. As it is seen the first two negative numbers do not have zero bytes in their representations.

However the number 256 in any case has such a byte at the very beginning of its internal representation. So the string will be outputted exactly eight times provided that sizeof( int ) is equal to 4.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335