0

I am using the library argp in C and I wonder why the two following things are not equivalent:

Code 1:

const char * const doc = "Welcome to my program";
struct argp argp = { NULL, NULL, NULL, doc };

Code 2:

const char doc[] = "Welcome to my program";
struct argp argp = { NULL, NULL, NULL, doc };

The first one does not compile with the error:

main.c:5:40: error: initializer element is not constant
struct argp argp = { NULL, NULL, NULL, doc };
main.c:5:40: note: (near initialization for ‘argp.doc’)

But in my mind const char doc[] was exactly the same as a constant pointer on char.

Note that both code were tested as global variables so in both case the lifetime of the variables should have been the same.

What am I missing?

Cosmo Sterin
  • 171
  • 8
  • https://stackoverflow.com/questions/1335786/c-differences-between-char-pointer-and-array does that help? – matt Apr 20 '20 at 16:52
  • Both variables are defined globally that's why I am confused about considerations on the stack scope. – Cosmo Sterin Apr 20 '20 at 17:01
  • @S.M. Conceptually, yes. The pointer would be pointing at something that is const. – matt Apr 20 '20 at 17:06
  • @CosmoSterin your first version compiles fine for me. I just did it in a main though. So maybe you're not including enough information? – matt Apr 20 '20 at 17:10
  • @S.M. Ok, it does! What happens here is that doc[] will be considered as an alias for a constant (the string "Welcome...") whereas in the second case it will not because it's a variable (no matter the const). That's because the C spec is very strict that behavior would not happen in C++ which is maybe why matt could compile it. – Cosmo Sterin Apr 21 '20 at 10:19

1 Answers1

1

There is a difference beween an array and a pointer.

In the first case, doc is a pointer, pointing to a block of memory containing that string. In the second case, doc is an array. There is no pointer. doc directly contains the items.

Both can be used when a (const char*) is needed somewhere, such as argument to printf(). But they are different. For the first, the pointer is passed. For the second, the address of doc is passed. This happens implicitly.

For example, build this little program:

#include <stdio.h>
int main()
{

        const char a[] = "abcdefghijkl";
        const char *b = "ijklmnopqrst";

        printf("sizeof(a) = %d\n",(int)sizeof(a));
        printf("sizeof(b) = %d\n",(int)sizeof(b));
        return 0;
}

Output is:

sizeof(a) = 13
sizeof(b) = 8

When leaving out the 'const' for now, you could also assign a new pointer to the pointer variable, but not to the array variable.

Blindleistung
  • 672
  • 8
  • 21
  • a[] will implicitly have a '/0' character at the end. Will that happen for *b? – mercury0114 Feb 14 '23 at 09:55
  • The *b = "..." line will generate a static string in the data segment, and create a pointer-var 'b', sizeof like void* , and pre-init it to the const string. The string has a null-terminator. Sizeof(b) will return 4 or 8 depending on arch. – Blindleistung Feb 14 '23 at 12:57