1

String a, that is a pointer, contains 5 1's, but printf outputs only one 1.

    #define _XOPEN_SOURCE
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <cs50.h>

    int h = 0;
    char b = '1';
    void f(string* a, int iter, int level)
    {

        if (h == 0)
        {
            a= calloc(iter, sizeof(char));
            ++h;
        }   
        if (level < iter)
        {
            a[level] = &b;
            f(a, 5, ++level);
        }
        else
        {   
            char c = '\0';
            a[level] = &c;
            printf("%c, %c, %c, %s\n", *a[0],*a[1],*a[2],*a);
        }
    }
    int main()
    {
        string c = "\0";
        f(&c, 5, 0);   
    }

output

    1, 1, 1, 1
2

*a is same as a[0], pointing to the first element of a. Generally, *(a + i) is same as a[i].

I don't think you want an array of strings (string is a typedef of char*) all pointing to the same variable (and it's dangerous to use %s with &b, as you don't know where the next zero byte is!), I assume you want an array of char instead (don't forget space for the null terminator then)

Edit: Strings in C

Strings in C are a bunch of non-zero characters (the value, not the digit '0' found in ASCII which is 48) ended by a zero byte 0 (the null terminator '\0' is a 0 cast to char), stored contiguously somewhere in memory. If a function like printf expects a string, it expects the memory address of the first of those characters, and will likely read from there until it hits a '\0', assuming everything including that final byte to be part of the string. So when you pass &b for a string, it will also process the byte next to it, and if that is not zero, will print even more, potentially giving out secrets, or triggering segmentation faults (which might be the lesser evil).

As there are padding bytes inserted to have all variables start at a memory address that's a multiple of their size, and those are initially zero in most case, such mistakes sometimes remain hidden in simple tests, as printf will take a padding byte for the null terminator.

With functions like scanf, there are even more potential issues (buffer overflows), unless you specify the maximum length you provide space for. A single char could take a string of zero characters (empty string) only.

  • 1
    Can you please elaborate why it is dangerous to use %s with &b? – Nikita Kokorin Dec 5 '18 at 0:45
  • 1
    Added some lengthy explanation, hope it helps more than it confuses. – Blauelf Dec 5 '18 at 7:44
1

Since a is a pointer, *a dereferences the pointer. I would fumble over the explanation, but found this post (cited here) a great resource. The variable is named p in this example, not a, with the value "abc".

To refer to the characters p points to, we dereference p using one of these notations (again, for C):

assert(*p == 'a');  // The first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
                     // p and 1 times the size of the things to which p points:
                     // In this case they're char which are 1 byte in C...
assert(*(p + 1) == 'b');  // Another notation for p[1]

Bottom line: use a in the printf, not *a.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .