Compilation difference C and C++ - c++

I have a piece of code which looks like
#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct hostent *server;
server = gethostbyname(argv[1]);
struct in_addr * address=(in_addr * )server->h_addr;
fprintf(stderr,"[%d] [%s] server [%s] \n",__LINE__,__func__,inet_ntoa(*address));
}
When i use g++ compiler it gets compiled but the same gives the following error with gcc compiler
myclient.c: In function ‘main’:
myclient.c:10:31: error: ‘in_addr’ undeclared (first use in this function)
myclient.c:10:31: note: each undeclared identifier is reported only once for each function it appears in
myclient.c:10:41: error: expected expression before ‘)’ token
Am I missing something here?

You should use struct in_addr, not just in_addr in c code (when casting too).

It's important to note that C has multiple namespaces. The general namespace
includes typedefs and other identifiers, but there is a separate namespace for
structs, enums, and unions tags; another one for labels, and also each struct
has it's own namespace. In code like this:
struct name {
int name;
} name;
name means 3 completely different things and this is perfectly legal. To
avoid typing the struct keyword, programmers often typedef a new name for
the struct and its tag:
typedef struct name {
int name;
} my_struct;
my_struct s1; /* easier than: struct name s1 */
my_struct s2;
In this last example name can even be omitted, unless you want to use a
pointer to the struct inside itself. This practice was so common that in C++
the compiler considers the tag a defined type for structs. This is perfectly
legal in C++:
struct my_struct {
int name;
};
my_struct s1;
my_struct s2;
And indeed is what's happening in your program. You're using the struct tag as
a type, but it's only a valid type in C++. You have two alternatives:
1.Typedef the struct in its declaration
typedef struct in_addr {
/* ... */
} in_addr;
2.Use the struct keyword to refer to the struct type
(struct in_addr *)
The first one is not applicable since you didn't declare the struct. It
already comes that way. So I'd stick with the second.

Change:
struct in_addr * address=(in_addr * )server->h_addr;
to:
struct in_addr * address=(struct in_addr * )server->h_addr;
Also, C (before C99) only allows variable declarations at the top of a block, and struct in_addr * address isn't.

C and C++ have different rules for struct types; in C++, the keyword struct creates a class type where all members are public by default. This type name can stand on its own, unlike in C.
C++ is not merely a superset of C, and there's plenty of code that will compile as one but not the other, or will behave differently because of different semantics.

Related

typedef struct vs struct - storage size of ‘struct' isn’t known [duplicate]

This question already has answers here:
storage size of ‘names’ isn’t known
(3 answers)
Closed 4 years ago.
I am trying myself out at bluetooth programming and came along this problem I do not understand. Basically, when I am using the typedef struct defintion the compiler throws the error:
temp_testcode.c:11:23: error: storage size of ‘head’ isn’t known
The code, compiled simply via gcc temp_testcode.c is as follows:
#include <stdint.h>
typedef struct {
uint8_t code;
uint8_t ident;
uint16_t len;
} __attribute__ ((packed)) l2cap_cmd_hdr;
/**
struct l2cap_cmd_hdr {
uint8_t code;
uint8_t ident;
uint16_t len;
};
*/
int main(int argc ,char* argv[]) {
struct l2cap_cmd_hdr head;
}
Though once I use the lower definition of a struct (currently commented out) the code compiles perfectly fine. So either it's a problem with the typedef struct or with the __attribute__ ((packed))
The previous stackoverflow posts about typedef structs did not help me out (typedef struct vs struct definitions), since I do not know how to make the the struct initialization in the main method work using the typedef struct (and not my currently commented out version). Something which is necessary because the bluetooth header files all define their structs like this.
So:
How do I make the struct initialization in the main method work using the typedef struct?
Why doesn't my code work?
Thank you for your time and help!
Typedefs and structs are in two different namespaces. That means the typedef l2cap_cmd_hdr is distinct from the struct struct l2cap_cmd_hdr.
You're trying to create an instance of the latter, which doesn't exist. You do have an instance of an anonymous struct that is typedef'ed as l2cap_cmd_hdr, so you can create that:
l2cap_cmd_hdr head;

Extern unnamed struct object definition

I got a global object of type "unnamed-struct" and i'm trying to define it. I don't want to pollute my global namespace with such useless type (it will be used only once).
Global.h
extern struct {
int x;
} A;
Is there any correct way to define such object?
I was trying this:
Global.cpp
struct {
int x;
} A = { 0 };
But VS2012 throws "error C2371: 'A' : redefinition; different basic types". Thanks.
One possible solution: create another file Global_A.cpp that does not include Global.h, and define A there. By the equivalent-definition rule this will be valid, as long as the anonymous struct definitions are equivalent.
This is still a bad idea, and most compilers will warn about it e.g. (gcc): warning: non-local variable `<anonymous struct> A' uses anonymous type.
There is no way to do just this simply because it would be error prone: some time in the future someone (probably even you) may want to modify this structure's definition and he might forget to do this in the header and source files accordingly. So you will have to invent a name for this structure and use its name the source file and leave its definition up to the header.
I don't know if this helps you, and this my first post... So take it easy.
I just ran into this issue and what I did was I added a function that manipulates the struct to the file that contained the anonymous struct. That way I can call that function from any file in my project, and it manipulates the values in the struct for me.
Here is an example:
header.c has this anonymous struct:
struct
{
char line1[80];
char line2[80];
char line3[80];
} header;
I want to manipulate those values in "interface.c" because I am making a command line interface in another file. My first instinct was to use an extern, but it seems like adding the following function to header.c is just as good or better (Some people discourage the use of externs when avoidable).
void changeHeaders(char *one, char *two, char *three);
void changeHeaders(char *one, char *two, char *three)
{
strcpy(header.line1, one);
printf("\nHeader 1: %s", header.line1);
strcpy(header.line2, two);
printf("\nHeader 2: %s", header.line2);
strcpy(header.line3, three);
printf("\nHeader 3: %s", header.line3);
}
Now as long as I include the prototype for that function I can manipulate those struct variables from any file by using that function. Hope that helps someone.

Emulate access specifiers in C

Is it possible to emulate C++ access specifiers [public, private, protected] in C ? More generally, how does the C++ compiler ensure that private members of a class are not accessed by non-member functions ?
C++ access control is entirely a figment of the compiler's imagination: you can't access a private member only because the compiler will refuse to compile any code that tries to do so.
It's actually fairly simple to access a private member of a C++ class by tricking the compiler into thinking that a pointer to an instance of ClassWithPrivateMember is actually a pointer to an instance of ClassWithPublicMember -- i.e., by using a slightly modified header file, you can generally get access to things you shouldn't. Not that anyone ever does anything like that...
The best way to do access control in C is by passing around pointers to an opaque type: struct objects the definition of which is not available to client code. If you provide a foo* create_foo() method and a series of methods that operate on foo*, hiding the actual definition of foo from the client, then you'll have achieved a similar effect.
// File "foo_private.h"
struct foo {
int private1;
char private2;
};
// File "foo.h"
typedef struct foo foo;
foo * create_foo(int x, char y);
int mangle_foo(foo *);
// file "foo.c"
#include <stdlib.h>
#include "foo.h"
#include "foo_private.h"
foo * create_foo(int x, char y) {
foo * f = (foo *) calloc(1, sizeof(foo));
f->private1 = x;
f->private2 = y;
}
int mangle_foo(foo *f) {
return f->private1 + f->private2;
}
Now, you distribute foo.c compiled into a library, along with foo.h. The functions declared in foo.h form the public interface of a type, but the internal structure of that type is opaque; in effect, the clients who call create_foo() can't access the private members of the foo object.
Our friend the FILE* is a similar sort of thing, except that the type FILE isn't usually truly opaque. It's just that most people (wisely) don't go poking through its innards. There, access control is enforced merely by obscurity.
I would advise strongly against using void* pointers as suggested in another answer (since fixed), that throws away all type-safety. You can instead forward-declare struct foo; in a header without specifying the contents, then you can pass those structs and pointers to them in and out of interface functions declared in a header. The struct implementation is hidden inside that unit's .c file.
If you want to keep the option of changing between a struct and other types e.g. int, you can use typedef in your header to wrap the type for the interface.
Other techniques you can use include declaring functions inside that .c file static so that they cannot be linked from other sources, even if those other sources declare the function.
There are many ways to achieve the goal, followings are mine:
The example includes a class "struct test_t" and a class function "test_create" and a member function "print"
test.h:
struct test_t {
// Member functions
void (*print)(struct test_t *thiz);
// Private attributes
char priv[0];
};
// Class functions
struct test_t *test_create(int number);
test.c:
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
// priv attr
struct test_priv_t {
int number;
};
// member functions
static void print(struct test_t *thiz)
{
struct test_priv_t *priv = (struct test_priv_t*)thiz->priv;
printf("number = %d\n", priv->number);
}
// Class functions
struct test_t *test_create(int number)
{
struct test_t *test = (struct test_t *)malloc(sizeof(struct test_t) + sizeof(struct test_priv_t));
// setup member function
test->print = print;
// initialize some priv attr
struct test_priv_t *priv = (struct test_priv_t*)test->priv;
priv->number = number;
return test;
}
main.c:
#include "test.h"
int main()
{
struct test_t *test = test_create(10);
test->print(test);
}

C code does not work when coded like C++

Hello Developers! I am learning algorithms from Algorithms Design Manual Book by Skiena. There I have the following code:
#include <stdio.h>
#include <stdlib.h>
typedef int item_type;
typedef struct{
item_type item;
struct list* next;
}list;
void insert_list(list **l, item_type x){
list *p;
p = malloc(sizeof(list));
p->item = x;
p->next = *l;
*l = p;
}
int main(){
return 0;
}
It gives me Warning when compiled:
gcc -Wall -o "test" "test.c" (in directory:
/home/akacoder/Desktop/Algorithm_Design_Manual/chapter2) test.c: In
function ‘insert_list’: test.c:15: warning: assignment from
incompatible pointer type Compilation finished successfully.
But when I rewrite this code as C++:
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef int item_type;
typedef struct{
item_type item;
struct list* next;
}list;
void insert_list(list **l, item_type x){
list *p;
p = malloc(sizeof(list));
p->item = x;
p->next = *l;
*l = p;
}
int main(){
return 0;
}
It gives the following:
g++ -Wall -o "chapter2" "chapter2.cpp" (in directory:
/home/akacoder/Desktop/Algorithm_Design_Manual/chapter2)
chapter2.cpp:15: error: conflicting declaration ‘typedef struct list
list’ chapter2.cpp:14: error: ‘struct list’ has a previous declaration
as ‘struct list’ chapter2.cpp: In function ‘void insert_list(list**,
item_type)’: chapter2.cpp: In function ‘void insert_list(list**,
item_type)’: chapter2.cpp:19: error: invalid conversion from ‘void*’
to ‘list*’
Can anyone explain why it is so? And How can I rewrite it in C++?
This is because c++ is stricter than c with respect to type conversions.
There are host of other errors in your code. Please note that just putting a c source code, renaming the file as .cpp & compiling using g++ does not make a c source code as c++.
If you are writing a program in c++ please use new & not malloc, doing so you do not need to explicitly type cast as in case of malloc.
Your problem in both cases is in the struct definition: struct list *next doesn't refer to the struct you are in the process of declaring. Try this instead:
typedef struct list {
item_type item;
struct list* next;
} list;
In addition, in C++ you must cast the void * returned by malloc to the appropriate pointer type (list *), C++ is stricter about these things. Also, BTW, in C++ you can leave off the typedef completely if you want.
The reason for the differing error messages is a difference in the languages.
In C, the compiler knows that struct list * is a pointer to a struct, so it doesn't need to complain that it doesn't actually know what a "struct list" is yet. Later, though, when you try to assign this "struct list *" from a pointer of type "list *" (the type of which is "pointer to an anonymous struct"), it complains about the mismatch.
In C++, a "struct" declaration is more or less equivalent to a "class" declaration (the major difference is in the default visibility of members). Among other things, this means that structs in C++ are more or less automatically typedefed. So when the compiler sees "struct list *next", it takes it as a forward declaration of a class named "list"; then when it finishes the statement and processes the typedef, throws an error because you're trying to typedef something to an identifier that is already (forward-)declared as something else. Then it issues further errors because it doesn't actually know what "list" might be, due to the earlier error.
C++ does not allow arbitrary pointer conversions, while C does. But since this is not considered good style, the compiler emits a warning.
Just add a cast and it will solve both messages:
p = (list*)malloc(sizeof(list));
Or if you want to be C++ only:
p = new list;
But then, you should declare constructors and such, also.
This is explained in this link.
Quote:
Gotcha for a C++ programmer using C
Structs and Enums
You have to
include the struct keyword before the name of the struct type to
declare a struct: In C++, you could do this
struct a_struct {
int x; };
a_struct struct_instance;
and have a new instance of a_struct called struct_instance. In C,
however, we have to include the struct keyword when declaring
struct_instance:
struct a_struct struct_instance;
In fact, a similar situation also holds for declaring enums: in C, you
must include the keyword enum; in C++, you don't have to. As a side
note, most C programmers get around this issue by using typedefs:
typedef struct struct_name {
/* variables */ } struct_name_t;
Now you can declare a struct with
struct_name_t struct_name_t_instance;
But there is another gotcha for C++ programmers: you must still use
the "struct struct_name" syntax to declare a struct member that is
a pointer to the struct.
typedef struct struct_name {
struct struct_name instance;
struct_name_t instance2; /* invalid! The typedef isn't defined
yet */ } struct_name_t;
You need to change this class:
typedef struct{
item_type item;
struct list* next;
}list;
to this:
struct list {
item_type item;
list* next;
};
Explanation: in the first example, you have anonymous structure, inside which struct list is forward declared. So when compiler sees typedef on the next line it finds a name collision, because typedef is not the same as struct declaration in C++.
Since what you're doing is really defining a struct and then creating an alias with the typedef I think it's more readable to do this in the C case:
typedef struct list_ {
item_type item;
struct list_* next;
} list;
Use the following code
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef int item_type;
struct list{
item_type item;
list* next;
};
void insert_list(list **l, item_type x){
list *p;
p = (list*)malloc(sizeof(list));
p->item = x;
p->next = *l;
*l = p;
}
int main(){
return 0;
}
What C only warns against, C++ is likely to consider an error.
It's a programming cultural thing. C was very forgiving in not enforcing it's typing system. C++ is still quite forgiving, but you're doing something in C that even C++ won't forgive.
When you malloc that block of memory, cast it to a pointer to a list. That will covert the address (pointer) to a pointer of the right type.
Without that cast, you could have malloc'd the size of anything, and there's no telling if it was meant to be referenced by a list pointer or some other pointer.

Using Structs -- Odd Issue

Been awhile since I've used structs in C++.
Any idea why this isn't working? My compiler is complaining about DataStruct not being a recognized type but Intellisense in VC++ is still able to see the data members inside the struct so the syntax is ok...
Frustating. xD
struct DataStruct
{
int first;
};
int main(int argc, char **argv)
{
DataStruct test;
//test.first = 1;
}
Are you sure you are compiling the file as C++? If you compile it as C (i.e. if the file has a .c rather than a .cpp extension), you will have problems.
You are compiling as C code. C requires you to refer to it using the "Struct" keyword or typedef it. C++ does not.
You need to use struct DataStruct to refer to the struct.
Alternatively, you can typedef it as DataStruct if don't want to use the "struct" everywhere.