compiler context
First off, I'm currently using Microsoft Visual Studio Community 2022 (64-bit) - Current Version 17.7.5. (Just in case this question is more about the tools I'm using than the language and I'm mistaken when suggesting this is about the c language itself.)
question foundation
Case 1 below gives this error: expression must be a modifiable lvalue
/* case 1 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char* defaultlist[] = { "string 1", "string 2" };
char** getlist() { return NULL; }
int main( int argc, char* argv[] ) {
char* list[]= getlist(); /* line with declaration I'm accustomed to using in past */
if ( list == NULL )
list = defaultlist; /* line with error message */
return 0;
}
Case 2 is fine:
/* case 2 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char* defaultlist[] = { "string 1", "string 2" };
char** getlist() { return NULL; }
int main( int argc, char* argv[] ) {
char** list= getlist(); /* modified declaration */
if ( list == NULL )
list = defaultlist; /* no error, anymore */
return 0;
}
In my ancient past there was no semantic difference whatsoever between a declaration that says char** p and one that says char* p[]. They had identical semantics in all declaration contexts in the 1970's, 1980's, and 1990's when I spent more time with c, than of late. (If I'm wrong about that, I'd like a stern correction and an example demonstrating the difference.)
I'm now observing a complaint from the compiler that suggests a new semantics I've not been accustomed to, previously. It seems that now, c compilers have decided that char* list[] is really char* (* const list). Which isn't my intention.
question
The following points should be addressed:
- Am I mistaken in asserting the declaration semantics of
char** pandchar* p[]were at some point identical? If so, and if it has always been different even back to the 1978 when I first learned C working on the Unix v6 kernel code, then exactly how has it been different and how might I have detected the difference had I tried to do so? (I have many old compilers here that I can use for testing purposes.) - Am I correct in recognizing that the declaration semantics of
char** pandchar* p[]are now different in the sense thatchar* p[], in certain circumstances I've yet to learn about, are actually taken aschar* (* const p)and that this change occurred in some revision to the c standard? (Or some other semantic meaning I missed considering?) - When was the change made, assuming I am right that a change was made in the standard?
char** pand one that sayschar* p[]" – when they are function arguments.char* list[]is an array of pointers. It can't be initialised with a function call (except with braces),listwill never beNULL, andlist = defaultlist;is an invalid assignment.char* list[] = { getlist() };butchar** getlist() { return NULL; }would then be incorrect: one starchar* getlist() { return NULL; }