0

While creating strjoin I noticed a strange phenomenon. When outputting a value strs in function strjoin()

These results were printed

123

Why?

#include <stdio.h>
#include <stdlib.h>

char    *strjoin(int size, char **strs, char *sep)
{
    char *new;

    if (!(new = malloc(sizeof(char) * size)))
        return (NULL);

    printf("%s", strs[1]);
    return (NULL);
}

#include <unistd.h>

int     main(void)
{
    char* b[4] = {"123", "456", "789", "245"};
    char *p;
    int i = 0;
    int size = 5;
    char a[4] = {',', 'a', 'b', '\0'};

    p = *b;

    strjoin(5, &p, a);
}
16
  • 3
    sizeof (char) always equals to one then redundant. Commented Feb 4, 2020 at 19:53
  • 1
    Express exactly what do you want? Commented Feb 4, 2020 at 19:55
  • 2
    Your array has 4 elements, so I'm not sure why are you requesting 5 of them. "123" is shown twice because p is located after b on stack (hence, has lower address). You're passing address of p, but it is only 1 element, so indexes greater than 0 actually reference values from b, e.g. strs[1] is b[0]. Commented Feb 4, 2020 at 19:56
  • 2
    @EsmaeelE, Since C99(?), the return 0 can be omitted from main. Commented Feb 4, 2020 at 20:06
  • 2
    @EsmaeelE, Poppycock. You can target C99 if you want to. (And it's over 20 years old now!) Furthermore, the linked post isn't relevant. I didn't say to change the declaration, only that the return EXIT_SUCCESS; is optional according to the C language, even when declared as int main(...). (In fact, main must be declared to return int in C99.) Note that I didn't mention any compiler or version thereof. Commented Feb 4, 2020 at 20:58

1 Answer 1

9

In order for it to be valid to use the value referenced by str[1], str must point to an array of at least two char* elements. In your demonstration, it points to p, which is a single char*. Your program therefore invokes Undefined Behaviour, and thus your program is invalid.

It's unclear what you are trying to accomplish. Perhaps you wanted

char **p = &( b[0] );
strjoin(4, p, a)

Keep in mind that an array used where a pointer is expected degenerates into a pointer to its first elements, so the above is equivalent to the following:

char **p = b;
strjoin(4, p, a)

or simply

strjoin(4, b, a)

(The first parameter to strjoin isn't being used in your demonstration, but I imagine it's expected to be the number of elements in *str, so I have adjusted it the argument accordingly.)

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much I understand!
Excellent answer. Clarification No need to use extra double pointer to pointer char **p.
@EsmaeelE, Are you saying there's no reason to use p? The answer already demonstrates that.
"...an array used where a pointer is expected...." -- It might be helpful to be more explicit about this. Arrays decay to pointers to their first elements in most expressions, the exceptions being when the array is an operand to the unary & address operator, or when the array is an operand to the sizeof operator, or when the array is a string literal used to initialize an array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.