1

*** EDIT - I know it is a long post and I know I have used some 'interesting' language choices. And, I'm choosing to believe the three answers I've had so far were made with good intent - for that I thank you. But, I really must insist, if you are not willing to read the whole post thoroughly or if you don't understand what it is I am actually asking, please save both our time and refrain from posting. ***

I have been searching for an answer to exactly the same question posed here - same online course, same lecturer; I recognise the code from the video.

I quickly found solutions in the form of #define and using an enum, but that still didn't really solve how the lecturer got his code to compile; and, I would like to actually comprehend, not just make it work so, I tried to dig deeper.

The professor in question doesn't ever actually show the code compilation, it's always a "here's one I compiled earlier" scenario - so I had included the possibility the error was in that unseen stage as indicated by the two answers on the page: he may well have been using g++ or clang.

However, my search was most circuitous, leading me hither and tither across the net, and in my quest, before I came across the above linked answers and amongst other things I came across this video where at around the 9 minute mark he compiles this code:

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

const int ARRAY_LENGTH = 5;

void printarray(int myarray[ARRAY_LENGTH]) {

    for (int i = 0; i < ARRAY_LENGTH; i++){
        printf("%i, ", myarray[i]);
    }
    printf("\n");
}


int main (int argc, char **argv){   

    int a[ARRAY_LENGTH] = {1, 2, 3, 4, 5};
    int b[ARRAY_LENGTH] = {5, 4, 3, 2, 1};

    int *p = malloc(sizeof(int) * 567);

    printarray(a);
    printarray(b);
    printarray(p);

    free(p);

}

He uses a makefile that runs gcc with the -g -Wall flags and is on a mac (I think, please correct me if I am wrong). The internet tells me clang is the default compiler on macs, so maybe this is something to do with it (although I have no idea why that would be), but trying this code with g++ gives error: invalid conversion from ‘void*’ to ‘int*’ [-fpermissive].

I would just like to understand what is actually going on. Not that consts in C aren't actually constant, more like read-only; use #define/enum. I've read that (probably on here), I've understood it, I've re-written my code and successfully compiled using both methodologies. I've even compiled using const by separating the declaration and assignment. And, at this point, it's not about how the original lecturer compiled his code anymore - I've tested g++ it definitely works, and, if I'd have found that answer earlier I would probably be happily satisfied now with no further questions.

But, I didn't. And, none of what I've found explains how the code from the video compiled and ran (or, why multiple people think this is good practice C coding that should be shared as educational material, but that seems a secondary digression). Maybe its a simple typo, but I've checked and re-checked and I simply cannot find it. Hopefully, someone will be able to adequately put an end to the mystery that plagues me.

Thank you for your time in reading, it seems a bit long but I was trying to be thorough and avoid the all too common initial question-answer ping-pong. No doubt I have still neglected something of the utmost import - c'est la vie.

  • 2
    C and C++ are 2 different languages. Trying to compile C code with a C++ compiler will often not work – UnholySheep Jan 03 '22 at 22:16
  • 1
    In this case `int *p = malloc(sizeof(int) * 567);` is valid C code, but not valid in C++, which is why `g++` gives you the error – UnholySheep Jan 03 '22 at 22:19
  • f you are sticking with the [tag:c] tag: The initialization error is because you are trying to initialize a VLA (_variable length array_). Use a constant expression, like `enum { ARRAY_LENGTH = 5 };` or `#define ARRAY_LENGTH 5,` and you can then do `int a[ARRAY_LENGTH] = {1, 2, 3, 4, 5};` - The array will no longer be a VLA but it'll compile. – Ted Lyngmo Jan 03 '22 at 22:35
  • 1
    FYI: The reason why this code compiles for the author of that video is because he's using Clang which seems to have the `gnu-folding-constant` extension turned on by default https://godbolt.org/z/PPvfGos57 – UnholySheep Jan 03 '22 at 22:52
  • @UnholySheep looking at the video it seems that the author is using gcc. – anastaciu Jan 03 '22 at 23:09
  • 1
    @anastaciu It's clearly recorded on macOS where by default `gcc` is an alias for `clang`. Either that or the author is using some strange version of GCC which performs non-standard constant folding – UnholySheep Jan 03 '22 at 23:13
  • @UnholySheep, the alias situation would explain it, but for the fact that no warning is shown, `-Wall` flag is being used. – anastaciu Jan 03 '22 at 23:14

1 Answers1

2

This is a result of constant folding in the clang compiler.

The instructor is compiling the program on a Mac, and on that platform "gcc" is an alias for "clang". While gcc does not perform this folding for a VLA, clang does.

From the clang documentation (version 10):

Differences between all c* and gnu* modes:

  • c* modes define __STRICT_ANSI__.
  • Target-specific defines not prefixed by underscores, like “linux”, are defined in gnu* modes.
  • Trigraphs default to being off in gnu* modes; they can be enabled by the -trigraphs option.
  • The parser recognizes asm and typeof as keywords in gnu* modes; the variants __asm__ and __typeof__ are recognized in all modes.
  • The Apple “blocks” extension is recognized by default in gnu* modes on some platforms; it can be enabled in any mode with the -fblocks option.
  • Arrays that are VLA’s according to the standard, but which can be constant folded by the frontend are treated as fixed size arrays. This occurs for things like int X[(1, 2)];, which is technically a VLA. c * modes are strictly compliant and treat these as VLAs.
dbush
  • 205,898
  • 23
  • 218
  • 273
  • It seems that starting with version 12 Clang does emit a warning about this, but presumably the version that ships with macOS is older – UnholySheep Jan 03 '22 at 23:31