Stack Overflow Asked by dablyputs on November 27, 2021
I’m having some trouble wrapping my head around pointer assignments in C. The asterisk character appears in many different locations and I don’t understand why I would choose to use one way over the other.
Specifically in the code below:
why would I choose:
conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);
over:
conn->db->rows = (struct **Address)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);
and within sizeof, what does the asterisk indicate?
This is the origin of the code above. Not the entire program.
struct Address {
int id;
int set;
char *name;
char *email;
};
struct Database {
int MAX_DATA;
int MAX_ROWS;
struct Address **rows; // USE ARRAY OF POINTERS
};
struct Connection {
FILE *file;
struct Database *db;
};
void die(const char *message) {
if(errno) {
perror(message);
} else {
printf("ERROR: %sn", message);
}
exit(1);
}
void Address_print(struct Address *addr) {
printf("%d %s %sn", addr->id, addr->name, addr->email);
}
void Database_load(struct Connection *conn) {
size_t i=0;
// Each database will have two `int` values. read
// those first.
assert(conn->db && conn->file);
if (!(conn->db && conn->file))
die("Database load : Invalid Connection info");
if (fread(&conn->db->MAX_DATA, sizeof(conn->db->MAX_DATA), 1, conn->file) != 1)
die("Database load : Couldn't read MAX_DATA");
if (fread(&conn->db->MAX_ROWS, sizeof(conn->db->MAX_ROWS), 1, conn->file) != 1)
die("Database load : Couldn't read MAX_ROWS");
conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);
assert(conn->db->rows);
if (!(conn->db->rows)) {
die("Database_load : Could not MAX_ROWS Address structures");
}
struct **Address
is illegal syntax. The base type is struct Address
and there should be nothing but whitespace (comments count as whitespace) between the struct
keyword and the tag, Address
.
struct Address *
is a type that is a pointer to a struct Address
.
struct Address **
is a type that is a pointer to a pointer to a struct Address
.
A sizeof
expression determines the size of a type in bytes. There are two forms:
sizeof(
type)
(for some type, type) specifies the type directly.sizeof
expression (for some expression, expression) uses the resulting type of expression without evaluating expression.In the case of sizeof(struct Address *)
, the first form is used. This is evaluated as the size of the struct Address *
type (pointer to struct Address
) in bytes.
In the statement:
conn->db->rows = (struct Address**)malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);
the result of the call to malloc
is a generic pointer type, void *
and it is being cast to the struct Address**
type by the cast operator (struct Address**)
to match the type of the rows
member being assigned to.
In C, it is actually the usual practice to omit the cast when assigning a void *
value to something of another object pointer type, or vice versa. The statement can be rewritten, omitting the cast, as:
conn->db->rows = malloc(sizeof(struct Address *) * conn->db->MAX_ROWS);
Additionally, the type operand of sizeof(
type)
can be replaced with an expression that has the same type. Since conn->db->rows
has type struct Address**
, then *conn->db->rows
or conn->db->rows[0]
will have type struct Address *
. Either of those could be substituted into the statement, rewriting it as, for example:
conn->db->rows = malloc(sizeof(*conn->db->rows) * conn->db->MAX_ROWS);
That can be less error-prone than specifying the type directly in the sizeof
expression, and is common practice.
Answered by Ian Abbott on November 27, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP