tags:

views:

204

answers:

7

I don't understand why is the last code block generating 1819043176 1870078063 6581362 0 1 2 3 4 0 6488159... These numbers are not random, but why those numbers? Thank you!

int main(void) {
    int x;
    int y[10];
    int* p;
    char* q;
    int k;
    char* prefix;

    k = 0;
    while (k < 10) {
            y[k] = k;
            k = k + 1;
    }
    x = 42;
    printf("address of y are %d %d %d\n", y, y + 1, y + 9);
    doit(y + 1);

    p = &y[0];
    printf("p is %d\n", p);
    *p = 42;
    p = p + 9;
    printf("p is %d\n", p);
    *p = 17;

    q = "hello world";
    p = "hello world";
    k = 0;
    while (k < 10) {
            printf("%d ", q[k]);
            k = k + 1;
    }
    printf("The end\n");

    k = 0;
    while (k < 10) {
            printf("%d ", p[k]);
            k = k + 1;
    }
    printf("The end\n");
}

doit

void doit(int p[9])
{
    char* prefix = "";
    int k = 0;
    printf("p is %d at address %d\n", p, &p);
    while (k < 10)
    {
        printf("%s%d", prefix, *p);
        prefix = ", ";
        k = k + 1;
        p = p + 1;
    }
    printf("\n");
}
A: 

The reason that (a) you're getting numbers printed and (b) that the numbers aren't random is because in the last code block, you're trying to print a string as decimals. After all, that's what %d expects to print - a decimal. That's not got anything to do with pointers.

You don't say what output you're expecting, but you have to chose the correct formatter to do that.

Another suggestion - the normal idiom for incrementing a variable in C and C++ is

++x;

or

x++;

to increment a value by 1 and

x += 9;

to increment it by more than 1 (obviously 9 in this case).

Timo Geusch
+5  A: 

1819043176 is 6C6C6568 in hexadecimal, which is stored as the bytes 68, 65, 6c, 6c on a little-endian machine. These are the first four characters of "hello world". And so on.

Normally you are not supposed to do these things in C, the results are undefined or implementation-dependent.

If you nevertheless want to peek around in memory then better do it in a more systematical way, for example write a small utility to do a hex dump.

starblue
A: 

I think it's because you are passing a char to printf when the format string is expecting an integer. Try casting q[k] and p[k] to integers.

while (k < 10) {
        printf("%d ", (int)p[k]);
        k = k + 1;
}

The call to printf() is not a normal function call, it uses varargs/stdargs and in those, the function needs to unpack the correct type.

So the first number in your output, 1819043176, corresponds to 0x6C6C6568. See how the character value for the lowercase 'h' (0x68) that you were presumably expecting to see is the least significant byte in four-byte integer? This is because the varargs routines were expecting an integer-sized argument because of the %d format specifier.

William Rose
A: 

This doesn't do what you think it does (I hope, maybe):

while (k < 10) {
        printf("%d ", q[k]);
        k = k + 1;
}

Think about what q is, what printf does, and what %d means (hint, look at the assignment of q). I would also suggest including the output of what you expect as a result because it's not obvious from the code what you're actually trying to accomplish (other than printing out pointers to ints using printf instead of ints).

Matt
+2  A: 

you have p pointing to the string "hello world"
but you have defined p as a pointer to integers, so p looks like this

p[0] = 'hell'
p[1] = 'o wo'
p[2] = 'rldx'
p[3] = 'xxxx'
p[4] = 'xxxx'
p[5] = 'xxxx'
p[6] = 'xxxx'
p[7] = 'xxxx'
p[8] = 'xxxx'
p[9] = 'xxxx'

where xxxx means you have not set this memory to anything.

lets look at p[0]
h=0x68
e=0x65
l=0x6c
l=0x6c

so you have the hexidecimal number 0x6c6c6568 which you can check is 1819043176

and so on
gnibbler
+4  A: 

I'm not digging enough to give you the answer, but I do have an important suggestion: crank up your compiler's warnings. When my bash starts up, it aliases gcc to /usr/bin/gcc -Wall -Wextra -Werror so that anything I try to compile has to pass through some of GCC's harshest tests (and it treats all warnings as errors, so minor mistakes won't compile). Your code gave me an error printout a mile long (not literally). Some errors:

  • printf() has a special format specifier for pointers: %p. Don't use %d - that's for ints.
  • p is an int * (pointer to an int), "hello world" is a char *. You can assign one to another, but it's usually a bad idea, so if you really want to do it, you should use a cast to say "Hey, I meant to do this:" p = (int *) "hello world";
  • main() doesn't return void, it returns an int. You know this, because you declared int main(void) like a good programmer, but then we get to the end of main() and there's no return statement! How is it supposed to return an int if you don't return anything? In C++, we can skip the ending return statement, but not in C (at least, we really shouldn't, because bad things can happen).

Also, you have a pattern that you repeat often:

k = 0;
while (k < 10) {
        y[k] = k;
        k = k + 1;
}

Welcome to for loops:

for(k = 0; k < 10; k++) {
        y[k] = k;
}

for() loops have three parts:

for(init; cond; inc)

init is run once before the loop, then the loop executes as long as cond is true, executing inc at the end of every loop. It is almost exactly equivalent to what you're doing, and is more concise.

Chris Lutz
Warnings aren't errors - many are just the compiler writers arbitrary style rules, and of course your warning-free code may well be anything but when you work with a different compiler with different arbitrary style rules. -1 for the obsession (which can result in unnecessarily awkward and cryptic code), but +2 for the suggestion, so I guess you still net an upvote.
Steve314
I know they're not strictly to be abided by, but (especially with GCC) they're preferences that are born to prevent certain things from happening. I don't like that GCC warns when I do `if(x = getstuff())` because sometimes I mean to write that, but making code compile under higher warnings levels will warn you about very questionable constructs in many cases. It's not the be-all, end-all of code correctness, but it helps keep you on top of your game. (Also, IMHO it's easier to learn when _not_ to bother with warnings than it is to learn when _to_ bother with warnings.)
Chris Lutz
@Chris - agreed, so sorry about the overreaction. I use MSVC++ more than GCC, and you get a lot of stupid warnings with that - e.g. performance warnings that basically nag at you to use int instead of bool for booleans.
Steve314
Wow, that's a terrible warning. GCC has some bad warnings, but it has about a million different flags to turn them off. If I dug through the documentation I could probably turn off the few warnings I don't want.
Chris Lutz
A: 

Your problem is about the variable p. it is int *, and sizeof an integer variable is 4 byte (it may change according to system and compiler) but the sizeof (char) is 1 byte

"hello world" string is 12 byte -with null- 12 byte can be defined in 3 integer.

after this line

p = "hello world";

only 3*4 memory of p will be used. (*p points array "y") Rest of them will be null...

H2O