redeclared as different kind of symbol error in C - c

I get the error 'J_TypeInstructions' redeclared as different kind of symbol' in the following C code:
struct _J_TypeInstructions {
const char *instructionName;
} J_TypeInstructions[] = { { "j", "000010" } };
//typedef struct _J_TypeInstructions J_TypeInstructions;

Try with that instead:
struct _J_TypeInstructions {
const char *instructionName;
} J_TypeInstructions[] = { {"j"}, {"000010"} };
/* ^ ^ */
and do not use a tag name like _J_TypeInstructions as identifiers beginning with _[A-Z]* are reserved in C.
EDIT: I missed the commented line was a part of the question:
typedef struct _J_TypeInstructions J_TypeInstructions;
You already declared a variable with the identifier J_TypeInstructions. You cannot declare a type with the same name of a variable in the same scope as identifiers for variables and type names live in the same name space. Change the name of your variable to fix the issue.

J_TypeInstructions can't be both variable name and type.
First, you created a variable(an array of _J_TypeInstructions structures) called J_TypeInstructions
then you try to define type with the same name as previously defined array.
Also, as ouah mentioned in his answer, fix your braces because the way you use them now is try to initialize one char * with 2 values and that's definetelly giving you a warning.

Related

Why can a typedef not share a name with an object but a tag can? [duplicate]

Quoting from here,
In C, there are two different namespaces of types: a namespace of struct/union/enum tag names and a namespace of typedef names.
name.c
$ cat name.c
#include<stdio.h>
typedef long long long2;
int long2 () {
return 4;
}
int main() {
printf("hello, world!");
return 0;
}
$ gcc name.c -o name
name.c:4: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$
name2.c
$ cat name2.c
#include<stdio.h>
int four() {
return 4;
}
struct dummy {
int member;
};
int main() {
struct dummy four;
}
$ gcc name2.c -o name2
$
I am trying to understand C namespace conflicts.
In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
C has four different name spaces for identifiers:
Label names (the goto type).
Tags (names of structures, unions and enumerations).
Members of structures and unions (these have a separate namespace per structure/union).
All other identifiers (function names, object names, type(def) names, enumeration constants, etc).
See also C99 6.2.3.
So your two question can be answered as:
Yes, function names and typedef names share the same name space.
No conflict, because the compiler will use scope rules (for function or object names). The identifier in main is said to shadow the global function name, something your compiler will warn you about if you set the warning levels high enough.
But the crucial point on your examples isn't about namespace, but the scope of the names.
In name.c, both long2 are "ordinary identifiers" (share the same name space), and both of them are defined in the same scope, so there is a conflict. (C99 §6.7/3)
If name2.c, the local variable four is in a scope deeper than the function four, so the variable hides the function four (C99 §6.2.1/4).
Your 2nd example does not show "no conflict". There is a conflict! Try this:
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
struct dummy four;
four.member = four();
}
And now this
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
int (*fx)(void) = four; /* "save" function */
struct dummy four; /* hide it */
four.member = fx(); /* use "hidden" fx */
}
In your 2nd example, the variable four hides the function four().
To answer your two questions quick.
Q1. In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
A1. Yes, identifiers for functions and typedef'ed types share the same namespace. So there's a conflict.
Q2. In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
A2. There's no conflict in your 2nd example even though the two identifiers named four belong to the same identifier namesapce, which is Ordinary namespace. Because the variable identifier four in the main is in a function scope, whereas the function identifier four in a file scope. So the latter one is hidden by the former one as the basic scope rule. If you move the variable four to the file scope(global) like below, you'll see an error.
...
struct dummy four; // Error! there's a previous definition
// in this file scope(global).
int main() {
// struct dummy four; // Commented out.
}
Actually, there are four different identifier namespaces: Label, Tag, Member, and Ordinary. You can find details about them at https://en.cppreference.com/w/c/language/name_space

How to define a struct in a struct and reuse the same name twice?

I have a simple C code example using a struct in a struct.
I need for documentation (doxygen) a named struct, in my example HermannS.
In doxygen I can refer to age with \ref ottoS::HermannS::age.
In doxygen I can not use \ref ottoS.name.age etc
For logic the name HermannS have to be the same.
Problem: But now the code create an redefinition-error
struct ottoS {
struct HermannS {
int age;
} name;
};
struct otherS {
struct HermannS {
int size;
} name;
};
int main ()
{
return 0;
}
I get the following error-message:
main.c:16:10: error: redefinition of ‘struct HermannS’
struct HermannS {
^~~~~~~~
main.c:10:10: note: originally defined here
struct HermannS {
^~~~~~~~
Question: how to define a struct in a struct and reuse the name HermannS ?
better Question: is there a gcc extension (prefix) to hide this error?
→ but this would be a very high price to pay for a simple doxygen documentation issue.
A struct declaration does not create a new namespace in C the way it does in C++, so you can't create type names that are "local" to a struct type. The tag name HermannS can only be used for one struct type definition.
C has four name spaces:
all labels (disambiguated by : or goto);
all tag names (disambiguated by struct, union, or enum)
member names (disambiguated by . or ->)
all other names (typedef names, enumeration constants, variable names, function names, etc.)
Unfortunately, what you're trying to do won't work in C - you'll have to use a different tag name for each inner struct definition.
You can't, as the compiler is telling you, and you really do not need to either. If you're not using that structure anywhere else, just don't name it:
struct ottoS {
struct {
int age;
} name;
};
struct otherS {
struct {
int size;
} name;
};
The only other (obvious) solution is to name the two inner structs differently.
If your logic/code/documentation is based on the fact that you need those two different structures to have the same name, then I would advise revisiting the logic, because it looks flawed.
is there a gcc extension (prefix) to hide this error?
No there is not. This is not a simple error, it's invalid C code: you are effectively defining two different types under the same name. The compiler will not be able to compile your code unless you avoid this.
C standard say in section 6.7.2.1 para 8
The presence of a struct-declaration-list in a
struct-or-union-specifier declares a new type, within a translation
unit.
So all structs within the same translation unit share the same namespace.
HermannS is redefined thus code is ill-formed.
Some workaround would be adding a prefix with the parent structure name:
struct ottoS {
struct ottoS_HermannS {
int age;
} name;
};
struct otherS {
struct otherS_HermannS {
int size;
} name;
};
Latest C standards allow the implementation to accept characters from the extended set like $. It will help avoid collisions with more conventional names. It works with gcc. However, the code will no longer be portable.
struct ottoS {
struct ottoS$HermannS {
int age;
} name;
};
struct otherS {
struct otherS$HermannS {
int size;
} name;
};
It mimics :: operator form C++ a bit. You could use some other unicode character and use it to postprocess your Doxygen documentation with sed-like tool. I mean replacing magic character with ::.
As the program is ill-formed it will not compile. However if struct HermannS is never used except the declaration then you could use the following trick.
If HermannS is removed then ottoS.name and otherS.name would become anonymous structs and the code would compile. All anonymous structs are independent types. Just pass -DHermannS= to the GCC's command.
gcc prog.c -DHermannS=
It will add a macro HermannS that expands to an empty token.
Do not pass this option to doxygen to let it generate a proper documentation.

Use of undeclared identifier when using struct?

When I try to assign char string_buffer in another struct it says
error use of undeclared identifier
I know that means it I need to declare string buffer in the current struct but is there a way without doing this.
struct ABC{
char string_buffer[64];
};
struct ABC *DEF(char *name){
name = string_buffer;
};
string_buffer is not a normal variable. It is a member variable of a variable of type struct ABC. You need to have a variable of type struct ABC and then, you need to access it usig the member access operator (. or ->), like
struct ABC sample = {0};
.... sample.name //valid access
Also, FWIW, based on your sample code, let me tell you, string_buffer is an array. You cannot assign the array the way you have shown in the sample snippet. In case you want to copy the content, you need to make use of strcpy().

c struct syntax with assignment?

I'm trying to get my head around structs. It seems ok in theory (e.g. a very concise and clear explanation: http://www.stanford.edu/class/cs110/hws/structs.html)
But then I find this in a code I'm messing with:
static struct pci_driver ik220_driver = {
name: DRV_NAME,
id_table: ik220_tbl,
probe: ik220_init_one,
remove: ik220_remove_one,
};
What does the = operator do here?
The = initializes a struct of type pci_driver, named ik220_driver, with the specified values for fields.
You are just assigning a variable, but it's a compound type.
Work it up in parts. struct pci_driver is a type. ik220_driver is a variable name. static sets the variable scope, so the rest: = {...} is specifying the value of the variable (which in this case happens to be a struct).

understanding C namespaces

Quoting from here,
In C, there are two different namespaces of types: a namespace of struct/union/enum tag names and a namespace of typedef names.
name.c
$ cat name.c
#include<stdio.h>
typedef long long long2;
int long2 () {
return 4;
}
int main() {
printf("hello, world!");
return 0;
}
$ gcc name.c -o name
name.c:4: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$
name2.c
$ cat name2.c
#include<stdio.h>
int four() {
return 4;
}
struct dummy {
int member;
};
int main() {
struct dummy four;
}
$ gcc name2.c -o name2
$
I am trying to understand C namespace conflicts.
In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
C has four different name spaces for identifiers:
Label names (the goto type).
Tags (names of structures, unions and enumerations).
Members of structures and unions (these have a separate namespace per structure/union).
All other identifiers (function names, object names, type(def) names, enumeration constants, etc).
See also C99 6.2.3.
So your two question can be answered as:
Yes, function names and typedef names share the same name space.
No conflict, because the compiler will use scope rules (for function or object names). The identifier in main is said to shadow the global function name, something your compiler will warn you about if you set the warning levels high enough.
But the crucial point on your examples isn't about namespace, but the scope of the names.
In name.c, both long2 are "ordinary identifiers" (share the same name space), and both of them are defined in the same scope, so there is a conflict. (C99 §6.7/3)
If name2.c, the local variable four is in a scope deeper than the function four, so the variable hides the function four (C99 §6.2.1/4).
Your 2nd example does not show "no conflict". There is a conflict! Try this:
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
struct dummy four;
four.member = four();
}
And now this
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
int (*fx)(void) = four; /* "save" function */
struct dummy four; /* hide it */
four.member = fx(); /* use "hidden" fx */
}
In your 2nd example, the variable four hides the function four().
To answer your two questions quick.
Q1. In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
A1. Yes, identifiers for functions and typedef'ed types share the same namespace. So there's a conflict.
Q2. In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
A2. There's no conflict in your 2nd example even though the two identifiers named four belong to the same identifier namesapce, which is Ordinary namespace. Because the variable identifier four in the main is in a function scope, whereas the function identifier four in a file scope. So the latter one is hidden by the former one as the basic scope rule. If you move the variable four to the file scope(global) like below, you'll see an error.
...
struct dummy four; // Error! there's a previous definition
// in this file scope(global).
int main() {
// struct dummy four; // Commented out.
}
Actually, there are four different identifier namespaces: Label, Tag, Member, and Ordinary. You can find details about them at https://en.cppreference.com/w/c/language/name_space

Resources