Search code examples
cvoidreallocgoto

Why I can't declare void * p in the end of longestCommonPrefix function?


I was solving leetcode problems in c when compiler gave me strange error. Why I can't declare void * p in the end of longestCommonPrefix function?

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

char * longestCommonPrefix (char ** strs, int strsSize) {
    int bufsize = 16;
    int len = 0;
    char * ans = malloc(bufsize);

    char ch;
    while (true) {
        ch = (*strs)[len];
        for (int i = 1; i < strsSize; i++) {
            if ((strs[i])[len] != ch || (strs[i])[len] == 0) goto _while_end;
        }
        if (len == bufsize) {
            bufsize += 16;
            void * p = realloc (ans, bufsize);
            if (!p) return NULL;
            ans = p;
        }
        ans[len++] = ch;
    }
_while_end:
    void * p = realloc (ans, len+1);
    if (!p) return 0;
    ans = p;
    ans[len] = 0;
    return ans;
}

int main () {
    char ** s = {"asdf", "asdw", "asdfe"};
    printf ("%s\n", longestCommonPrefix (s, 3));
    return 0;
}
main.c:27:2: error: expected expression
        void * p = realloc (ans, len+1);
        ^
main.c:28:7: error: use of undeclared identifier 'p'
        if (!p) return 0;
             ^
main.c:29:8: error: use of undeclared identifier 'p'
        ans = p;
              ^
main.c:35:15: warning: incompatible pointer types initializing 'char **' with an expression of type 'char [5]' [-Wincompatible-pointer-types]
        char ** s = {"asdf", "asdw", "asdfe"};
                     ^~~~~~
main.c:35:23: warning: excess elements in scalar initializer [-Wexcess-initializers]
        char ** s = {"asdf", "asdw", "asdfe"};
                             ^~~~~~
2 warnings and 3 errors generated.

Solution

  • In C, only statements can be labeled, not declarations. Declarations and statements are two separate categories. (In C++, declarations are included in statements, instead of separate, and can be labeled.) I do not believe there is a technical reason for this (such as some conflict in the formal grammar of the language); it is just a legacy of development of the C language.

    An easy workaround is simply to use a null statement, ;, with the label:

    _while_end:
        ;
        void * p = realloc (ans, len+1);