2

This piece of code swap the first and last element of a given array:

#include <stdio.h>

/* swap first and last element of array */
void fn(void *v, size_t length, size_t size)
{
    char *a = (char *)v;
    char *b = (char *)v + size * (length - 1);
    char temp;

    do {
        temp = *a;
        *a++ = *b;
        *b++ = temp;
    } while (--size > 0);
}

int main(void)
{
    int a[] = {0, 1, 2};
    double b[] = {0., 1., 2.};
    char c[][15] = {"Hello", ",", "this is a test"};

    fn(a, 3, sizeof(a[0]));
    fn(b, 3, sizeof(b[0]));
    fn(c, 3, sizeof(c[0]));
    printf("%d %d\n", a[0], a[2]);
    printf("%f %f\n", b[0], b[2]);
    printf("%s %s\n", c[0], c[2]);
    return 0;
}

Output:

2 0
2.000000 0.000000
this is a test Hello

My question is:

The code is safe?, it is guaranteed that c[0] is initialized by the compiler as

{'h', 'e', 'l', 'l', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

or c[0] may contain {'h', 'e', 'l', 'l', 'o', 0, [garbage]}?

EDIT: And if c is not initialized?

int main(void)
{
    char c[3][15];

    strcpy(c[0], "Hello");
    strcpy(c[1], ",");
    strcpy(c[2], "this is a test");
    fn(c, 3, sizeof(c[0]));
    printf("%s %s\n", c[0], c[2]);
    return 0;
}

Is it safe to use fn? (c[0] contains 9 bytes of garbage)

15
  • 1
    copying garbage wouldn't make that piece of code unsafe, as long as you don't need certain values behind NUL after swapping Commented Aug 25, 2014 at 15:38
  • 1
    no, you can copy whatever ther arrays may contain. Nevertheless, it would be interesting to know which answer is correct Commented Aug 25, 2014 at 15:47
  • 1
    From the C11-Standard's Annex J.2 "Undefined behavior": "The value of an object with automatic storage duration is used while it is indeterminate" So I'd say your update's use of fn() provokes UB for c's 1st and 2nd element. Commented Aug 25, 2014 at 16:17
  • 2
    However, the 1st rule to write robust and secure code is: "Always properly initialise all variables." Commented Aug 25, 2014 at 16:21
  • 1
    It was, if we replaced fn() by qsort() in EDIT's main(). I would have never have thought about that (and to be honest, I still wouldn't be too afraid if I saw it tomorrow in my code) Commented Aug 25, 2014 at 16:39

2 Answers 2

5

From the C11-Standard chapter 6.7.9:

21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration

So yes, c[0] will be fully initialised.

This was also defined by the C99-Standard (chapter 6.7.8/21). For ealier versions of the standard I don't know this (anymore ... ;-)).

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

1 Comment

Do you know if that has been defined like that for older standards as well?
2

You asked:

it is guaranteed that c[0] is initialized by the compiler as

{'h', 'e', 'l', 'l', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

Yes, the language guarantees that. It zero-initializes the elements of the array that are not explicitly initialized.

Comments

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.